Home > Blockchain >  When I change one GPIO pin output, others also change
When I change one GPIO pin output, others also change

Time:06-27

I implement GPIO via mmap in C. Now I need to use GPIO to simulate I2C, but when I change the output of one pin, the level of the other pin is pulled low. I think I use AND and OR operations to change the value of a pin will not change the value of other pins, what is wrong with my operation? here is my code and pic:

void i2cSDA(u8* map_base, bool isHigh)
{
    (*(volatile u32*)(map_base   GPIO_BASE_OFFSET   rPE_DAT)) = (isHigh) ?
    ((PE_DAT & 0XFFFFEFFF) | 0X00001000):
    ((PE_DAT & 0XFFFFEFFF));
}

void i2cSCL(u8* map_base, bool isHigh)
{
    (*(volatile u32*)(map_base   GPIO_BASE_OFFSET   rPE_DAT)) = (isHigh) ?
    ((PE_DAT & 0XFFFFF7FF) | 0X00000800):
    ((PE_DAT & 0XFFFFF7FF));
}

and in main.c:

int main(int argc, char** argv)
{
    static int dev_fd;
    unsigned char *map_base;

    dev_fd = open("/dev/mem", O_RDWR);

    map_base = (unsigned char *)mmap(NULL, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, dev_fd, GPIO_PAGE_OFFSET);

    i2cInit(map_base);

    i2cSCL(map_base, 1);
    i2cDely();
    i2cSDA(map_base, 1);

    i2cDely();

    i2cSDA(map_base, 0);

    i2cDely();

    i2cSDA(map_base, 1);

    i2cDely();

    close(dev_fd);

    return 0;
}

and PE_DAT is defined as u32 PE_DAT = (*(volatile u32*)(map_base GPIO_BASE_OFFSET rPE_DAT));

I use PE12 and PE11, the data register is 32 bits, 0:12 is data for PE0 to PE12, and 13:32 is reserved.

problem like this

When I try to pull the yellow line to high, the green line get low. Full Code is Here, mainly used I2C.h and GPIO.h.

CodePudding user response:

Your funcktions to set/clear bits are wrong:

void i2cSDA(u8* map_base, bool isHigh)
{
    (*(volatile u32*)(map_base   GPIO_BASE_OFFSET   rPE_DAT)) = (isHigh) ?
    ((PE_DAT & 0XFFFFEFFF) | 0X00001000):
    ((PE_DAT & 0XFFFFEFFF));
}

You never update PE_DAT which makes it contain old invalid values. Also your expressions are too complicated. This function should looke like this:

void i2cSDA(u8* map_base, bool isHigh)
{
    if (isHigh != 0)
    {
        (*(volatile u32*)(map_base   GPIO_BASE_OFFSET   rPE_DAT)) |= 0X00001000;
    }
    else
    {
        (*(volatile u32*)(map_base   GPIO_BASE_OFFSET   rPE_DAT)) &= 0XFFFFEFFF;
    }
}
  • Related