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

Accessing mapped global variable by reference

Hello,

I'm using the LPC2468 micro controller. I have a struct mapped to the I2C register and in the I2C interrupt I statically access that struct, and everything works fine.

I've since broken off into a separate function the processing part of the interrupt code and now the interrupt passes a reference to its register to that function (so I can use one function for the three I2C buses). And suddenly the code doesn't work. Just to make sure I didn't mess up anything when creating the new subroutine, I replaced all the by-reference register accesses with a static call, and it worked again. I also verified that the reference points to the correct address.

So, it seems that when accessing the register statically, it works, and when accessing by reference it doesn't work. I can't figure out why. Does anyone know what I'm doing wrong? Or is there some technical reason why this won't work?

Here's a code snippet:

struct i2c_regs {
        U32 I2CONSET;
        U32 I2STAT;
        U32 I2DAT;
        U32 I2ADR;
        U32 I2SCLH;
        U32 I2SCLL;
        U32 I2CONCLR;
} __attribute__((packed));

struct i2c_data {
        volatile struct i2c_regs *regs;
        U8 len;
        U8 pos;
        U8 addr;
        char *buf;
        char *base;
        U8 state;
        OS_MUT lock;
        OS_SEM sem;
};

static volatile struct i2c_regs i2c0_regs __attribute__((at(I2C0_BASE_ADDR)));

static struct i2c_data i2c0;
// i2c0.regs is properly initialized

void i2c0_handler(void) __irq
{
        IENABLE;
        i2c_master_handler(&i2c0);
        IDISABLE;
        VICVectAddr = 0;
}

static void i2c_master_handler(struct i2c_data *i2c)
{
        int status;

        status = i2c->regs->I2STAT;
        switch(status) {
            case I2C_STATUS_START:
#if 0
                // Doesn't work
                i2c->regs->I2DAT = i2c->addr;

                i2c->pos = 0;
                i2c->buf = i2c->base;

                i2c->regs->I2CONSET = I2CONSET_AA;
                i2c->regs->I2CONCLR = I2CONCLR_SIC|I2CONCLR_STAC;
#else
                // Does work
                i2c0_regs.I2DAT = i2c->addr;

                i2c->pos = 0;
                i2c->buf = i2c->base;

                i2c0_regs.I2CONSET = I2CONSET_AA;
                i2c0_regs.I2CONCLR = I2CONCLR_SIC|I2CONCLR_STAC;
#endif
                break;
        ...
}

Thanks,

Jon

Parents Reply Children
No data