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

 
 
> Траблы с контроллером 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
 
Start new topic
Ответов
alexadmin
сообщение Feb 19 2014, 06:16
Сообщение #2


Знающий
****

Группа: Свой
Сообщений: 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



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

 


RSS Текстовая версия Сейчас: 22nd July 2025 - 22:02
Рейтинг@Mail.ru


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