Перейти к содержанию
    

Траблы с контроллером IIC от Xilinx

Здравствуйте, уважаемые гуру.

 

Имеем девайс IIC (датчик температуры), висящий на Kintex 7.

Все это подключается к стандартному контроллеру IIC в XPS и Microblaze.

 

И вроде как все оно работает, НО.

Если попробовать сделать обмен типа "прочитать температуру":

1. Записать адрес датчика температуры

2. Записать регистр датчика температуры (0 - MSB темперетары)

3. Repeated Start

4. Записать адрес датчика температуры

5. Прочитать температуру

6. Стоп

 

То до п. 4 включительно все нормально, а потом контроллер IIC вылетает с ошибкой "потеря арбитража".

При этом, если вместо "Repeated Start" поставить "Stop", а затем "Start", то все нормально работает.

 

Внимание, вопрос: кто-нибудь сталкивался с подобным?

Какие могут быть причины, и как бороть?

 

Соединение точка-точка, никаких других мастеров на этой шине нет. Датчик мастером быть не умеет и не пытается. На Чипскопе и осцилле до п. 4 включительно все выглядит как надо.

 

Всем заранее спасибо за помощь.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Попробуйте поменять антиглитчевые задержки. Когда-то и где-то видел задержку SDA относительно SCL но в приложенной картинке этой задержки нет.

post-51826-1392739455_thumb.jpg

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я долго бился со стандартным API, но оно меня в итоге победило (точно так же зависало в процессе). В конце концов я написал вручную две функции доступа, немного пошаманил, помухлевал и в итоге работает, хотя тут тоже есть нюансы.

 

// Simple user-created API to IIC controller
// http://forums.xilinx.com/t5/Embedded-Processor-System-Design/Why-the-IIC-can-t-be-stopped/td-p/295693
u32 iic_write(u32 baseaddr, u32 daddr, u32 waddr, u32 wdata) {
    int stat2;
    u32 timeout;
    int stat = (Xil_In32(baseaddr + 0x104));
    if(stat != 0xc0)
    {
    //    print("Bad stat.");
        Xil_Out32((baseaddr + 0x100), 0xc0|0x02); // reset tx fifo
//        Xil_Out32((baseaddr + 0x100), 0xc0|0x03); // enable iic
    }
    Xil_Out32((baseaddr + 0x100), 0xc0|0x00); // disable iic
    Xil_Out32((baseaddr + 0x100), 0xc0|0x01); // enable iic

    Xil_Out32((baseaddr + 0x100), 0xc0|0x0d); // Start; Transmit
    Xil_Out32((baseaddr + 0x108), (0x100 | (daddr & 0xFE))); // send slave address for write
    Xil_Out32((baseaddr + 0x108), waddr); // send register address
    Xil_Out32((baseaddr + 0x108), (0x200 | (wdata & 0xFF))); // send data byte with stop bit
    timeout = 100; // timeout
    while(1)    // ToDo: add timeout to avoid hang up when I2C slave is not responding (no ACK)
    {
        stat2 = Xil_In32(baseaddr + 0x104);
        // wait for TX FIFO empty
        if( ((stat2 & 0x80) ) && ((stat2 & 0x04)== 0) )    // TX FIFO empty && Bus not busy
            break;
        if (timeout == 0) {
            xil_printf("iic write timed out %x %x\n\r", waddr, wdata);
            return 0xFFFFFFFF; // data not valid
        }
        timeout--;
        usleep(200);
    }
    return 0;
}


u32 iic_read(u32 baseaddr, u32 daddr, u32 raddr) {
    int stat2;
    u32 rdata, timeout;
    int stat = (Xil_In32(baseaddr + 0x104));
    if(stat != 0xc0)
    {
    //    print("Bad stat.");
        Xil_Out32((baseaddr + 0x100), 0x002); // reset tx fifo
        Xil_Out32((baseaddr + 0x100), 0x003); // enable iic
    }
    Xil_Out32((baseaddr + 0x100), 0x000); // disable iic
    Xil_Out32((baseaddr + 0x100), 0x001); // enable iic

    Xil_Out32((baseaddr + 0x108), (0x100 | (daddr & 0xFE))); // send slave address for write
    Xil_Out32((baseaddr + 0x108), raddr); // send register address
    Xil_Out32((baseaddr + 0x108), (0x101 | (daddr & 0xFE))); // send slave address for read
    Xil_Out32((baseaddr + 0x108), 0x201); // set stop after 1 data byte
    timeout = 100; // timeout
    while(1)
    {
        stat2 = Xil_In32(baseaddr + 0x104);
        if ((((stat2 & 0x40) == 0x0)) || (timeout == 0)) // (RX FIFO not empty && Bus not busy) or timeout    //  && ((stat2 & 0x04)== 0)
            break;
            //(((Xil_In32(IIC_BASEADDR + 0x104) & 0x40) == 0x40) && (timeout != 0)) { // wait for read FIFO not empty
        timeout--;
        delay_ms(1);
    }
    rdata = Xil_In32(baseaddr + 0x10C) & 0xFF; // read data byte
    delay_ms(1);
    if (timeout == 0) {
        xil_printf("iic read timed out %x %x\n\r", raddr, rdata);
        return 0xFFFFFFFF; // data not valid
    }
    return (rdata);
}

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Если читать Ваши комментарии так, как они написаны, то после записи адреса регистра Вы делаете стоп. Мне надо добиться, чтобы работал Repeated start, т.е. без стопа между записью номера регистра и чтением данных.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Если читать Ваши комментарии так, как они написаны, то после записи адреса регистра Вы делаете стоп. Мне надо добиться, чтобы работал Repeated start, т.е. без стопа между записью номера регистра и чтением данных.

 

Где?

 

Xil_Out32((baseaddr + 0x108), (0x100 | (daddr & 0xFE))); // send slave address for write

Xil_Out32((baseaddr + 0x108), raddr); // send register address

 

Вот тут идет рестарт с отправкой физического адреса устройства

Xil_Out32((baseaddr + 0x108), (0x101 | (daddr & 0xFE))); // send slave address for read

 

А теперь идет чтение (в данном случае одного байта) и после этого стоп

Xil_Out32((baseaddr + 0x108), 0x201); // set stop after 1 data byte

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ах да, в итоге прицепил контроллер с Opencores (тот самый, который Altera рекомендует).

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

...И тут выяснилось, что этот контроллер только мастер...

Граждане, понасоветуйте культурный I2C slave контроллер (с исходниками желательно на Verilog), чтобы к процессору хорошо цеплялся и библиотеки на Си чтоб были :).

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...