реклама на сайте
подробности

 
 
 
Reply to this topicStart new topic
> Траблы с контроллером IIC от Xilinx, Пока что контроллер побеждает!
Koluchiy
сообщение Feb 18 2014, 14:53
Сообщение #1


Знающий
****

Группа: Свой
Сообщений: 972
Регистрация: 12-04-09
Из: Москва
Пользователь №: 47 543



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

Имеем девайс IIC (датчик температуры), висящий на Kintex 7.
Все это подключается к стандартному контроллеру IIC в XPS и Microblaze.

И вроде как все оно работает, НО.
Если попробовать сделать обмен типа "прочитать температуру":
1. Записать адрес датчика температуры
2. Записать регистр датчика температуры (0 - MSB темперетары)
3. Repeated Start
4. Записать адрес датчика температуры
5. Прочитать температуру
6. Стоп

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

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

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

Всем заранее спасибо за помощь.
Go to the top of the page
 
+Quote Post
MadGarry
сообщение Feb 18 2014, 16:06
Сообщение #2


Участник
*

Группа: Свой
Сообщений: 74
Регистрация: 10-08-09
Из: Санкт-Петербург
Пользователь №: 51 826



Попробуйте поменять антиглитчевые задержки. Когда-то и где-то видел задержку SDA относительно SCL но в приложенной картинке этой задержки нет.
Эскизы прикрепленных изображений
Прикрепленное изображение
 
Go to the top of the page
 
+Quote Post
Koluchiy
сообщение Feb 18 2014, 16:14
Сообщение #3


Знающий
****

Группа: Свой
Сообщений: 972
Регистрация: 12-04-09
Из: Москва
Пользователь №: 47 543



Пробовал, не помогает.
Go to the top of the page
 
+Quote Post
alexadmin
сообщение Feb 19 2014, 06:16
Сообщение #4


Знающий
****

Группа: Свой
Сообщений: 572
Регистрация: 17-11-05
Из: СПб, Россия
Пользователь №: 10 965



Я долго бился со стандартным 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);
}

Go to the top of the page
 
+Quote Post
Koluchiy
сообщение Feb 19 2014, 08:27
Сообщение #5


Знающий
****

Группа: Свой
Сообщений: 972
Регистрация: 12-04-09
Из: Москва
Пользователь №: 47 543



Если читать Ваши комментарии так, как они написаны, то после записи адреса регистра Вы делаете стоп. Мне надо добиться, чтобы работал Repeated start, т.е. без стопа между записью номера регистра и чтением данных.
Go to the top of the page
 
+Quote Post
alexadmin
сообщение Feb 19 2014, 08:34
Сообщение #6


Знающий
****

Группа: Свой
Сообщений: 572
Регистрация: 17-11-05
Из: СПб, Россия
Пользователь №: 10 965



Цитата(Koluchiy @ Feb 19 2014, 12:27) *
Если читать Ваши комментарии так, как они написаны, то после записи адреса регистра Вы делаете стоп. Мне надо добиться, чтобы работал 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
Go to the top of the page
 
+Quote Post
Koluchiy
сообщение Feb 19 2014, 10:30
Сообщение #7


Знающий
****

Группа: Свой
Сообщений: 972
Регистрация: 12-04-09
Из: Москва
Пользователь №: 47 543



Извиняюсь, был неправ.

Да, вроде работает sm.gif.
Спасибо!
Go to the top of the page
 
+Quote Post
Koluchiy
сообщение Feb 27 2014, 14:32
Сообщение #8


Знающий
****

Группа: Свой
Сообщений: 972
Регистрация: 12-04-09
Из: Москва
Пользователь №: 47 543



Ах да, в итоге прицепил контроллер с Opencores (тот самый, который Altera рекомендует).
Go to the top of the page
 
+Quote Post
Koluchiy
сообщение Mar 7 2014, 15:22
Сообщение #9


Знающий
****

Группа: Свой
Сообщений: 972
Регистрация: 12-04-09
Из: Москва
Пользователь №: 47 543



...И тут выяснилось, что этот контроллер только мастер...
Граждане, понасоветуйте культурный I2C slave контроллер (с исходниками желательно на Verilog), чтобы к процессору хорошо цеплялся и библиотеки на Си чтоб были sm.gif.
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 21st July 2025 - 14:26
Рейтинг@Mail.ru


Страница сгенерированна за 0.01423 секунд с 7
ELECTRONIX ©2004-2016