Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: AT91SAM7X I2C
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
mungo
Много раз читал тут, что у людей аппаратный и-квадрат в этом камне не работает. Видел софтовые реализации.
Однажды я наткнулся на пример от атмела и сделал свою реализацию. Работает уже год без проблем.
Сначала запуск железа:
Код
AT91F_PMC_EnablePeriphClock(AT91C_BASE_PMC,(1<<AT91C_ID_TWI));
*AT91C_TWI_CWGR=0x033C3C;

Ну ессно и ножки включить, тут думаю каждый справится.
Далее собсна чтение:
Код
void    ReadI2C(char *s,unsigned count,char dev,word iaddr)
{
unsigned    i,stt,j;
if (count==0) return;
*AT91C_TWI_CWGR=0x030F0F;
*AT91C_TWI_CR=AT91C_TWI_MSEN;
stt=*AT91C_TWI_SR; while (!(stt&AT91C_TWI_TXCOMP)) {stt=*AT91C_TWI_SR;}
if (dev==0xD0) i=AT91C_TWI_IADRSZ_1_BYTE; else i=AT91C_TWI_IADRSZ_2_BYTE;
*AT91C_TWI_IADR=iaddr;
*AT91C_TWI_MMR=(dev<<15)|i|AT91C_TWI_MREAD;
if (count==1) {
*AT91C_TWI_CR=AT91C_TWI_START|AT91C_TWI_STOP;
stt=*AT91C_TWI_SR; while (!(stt&AT91C_TWI_TXCOMP)) {stt=*AT91C_TWI_SR;}
s[0]=*AT91C_TWI_RHR;
*AT91C_TWI_CR=AT91C_TWI_MSDIS;
return;
} else *AT91C_TWI_CR=AT91C_TWI_START;
s[0]=*AT91C_TWI_RHR;
for (i=0; i<count; i++) {
stt=*AT91C_TWI_SR; j=10000; while (!(stt&AT91C_TWI_RXRDY)&&--j) {stt=*AT91C_TWI_SR;}
if (!j) {error|=NOEEP; return;}
s[i]=*AT91C_TWI_RHR;
}
*AT91C_TWI_CR=AT91C_TWI_STOP;
stt=*AT91C_TWI_SR; while (!(stt&AT91C_TWI_TXCOMP)) {stt=*AT91C_TWI_SR;}
*AT91C_TWI_CR=AT91C_TWI_MSDIS;
}

И запись:
Код
void    WriteI2C(char *s,unsigned count,char dev,word iaddr)
{
unsigned    i,stt,j;
if (count==0) return;
switch (dev) {
    case    0xEE: i=AT91C_TWI_IADRSZ_NO; *AT91C_TWI_CWGR=0x033C3C; break;
    case    0xD0: i=AT91C_TWI_IADRSZ_1_BYTE; *AT91C_TWI_CWGR=0x030F0F; break;
    case    0xA6:
    case    0xA0: i=AT91C_TWI_IADRSZ_2_BYTE; *AT91C_TWI_CWGR=0x030F0F; break;
}
*AT91C_TWI_CR=AT91C_TWI_MSEN;
stt=*AT91C_TWI_SR; j=20000; while (!(stt&AT91C_TWI_TXCOMP)&&--j) {stt=*AT91C_TWI_SR;}
*AT91C_TWI_MMR=(dev<<15)|i;
*AT91C_TWI_IADR=iaddr;
if (count==1) {
*AT91C_TWI_CR=AT91C_TWI_START|AT91C_TWI_STOP;
*AT91C_TWI_THR=s[0];
stt=*AT91C_TWI_SR; j=20000; while (!(stt&AT91C_TWI_TXCOMP)&&--j) {stt=*AT91C_TWI_SR;}
*AT91C_TWI_CR=AT91C_TWI_MSDIS;
return;
} else *AT91C_TWI_CR=AT91C_TWI_START;
for (i=0; i<count; i++) {
*AT91C_TWI_THR=s[i];
stt=*AT91C_TWI_SR; j=20000; while (!(stt&AT91C_TWI_TXRDY)&&--j) {stt=*AT91C_TWI_SR;}
if (!j) {
error|=NOEEP;
return;}
}
*AT91C_TWI_CR=AT91C_TWI_STOP;
stt=*AT91C_TWI_SR; j=20000; while (!(stt&AT91C_TWI_TXCOMP)&&--j) {stt=*AT91C_TWI_SR;}
*AT91C_TWI_CR=AT91C_TWI_MSDIS;
}


В примере записи происходит переключение скоростей под разную переферию. Используются часы, два епрома и пик. Все работает!
aaarrr
Без прерываний, без контроля ошибок...

Я не хочу сказать, что I2C у SAM'ов полностью неработоспособен, в некоторых случаях - и работа с EEPROM тому пример - он вполне может работать.
Только недостатков слишком уж много:
- Поддержки PDC нет, зато случается Overrun (и это в мастер режиме!).
- С NXP мы не дружим (SAA7113 просто периодически выдает NAK'и).
- Про еррату и полностью неработоспособный слейв я вообще молчу.

Ну не стал бы, поверьте, Atmel заменять полностью модуль I2C в новых кристаллах, если бы все было в порядке.
mungo
На вкус и цвет...
Суть: ЭТО действительно работает, и если кто уже столкнулся, не нужно изобретать.
А насчет прерываний - а зачем? При операции записи ещё куда ни шло, а при чтении - в любом случае нужно ждать данных.
xelax
Цитата(mungo @ Jun 20 2008, 13:59) *
На вкус и цвет...
Суть: ЭТО действительно работает, и если кто уже столкнулся, не нужно изобретать.
А насчет прерываний - а зачем? При операции записи ещё куда ни шло, а при чтении - в любом случае нужно ждать данных.


А все остальные задачи тоже должны ждать пока I2C освободится??? 07.gif
aaarrr
Цитата(mungo @ Jun 20 2008, 13:59) *
А насчет прерываний - а зачем? При операции записи ещё куда ни шло, а при чтении - в любом случае нужно ждать данных.

А при записи ждать не нужно что-ли?

Насчет прерываний смотрите первый из недостатков, упомянутых мной в предыдущем посте. Не успели обслужить I2C - вылетели с треском в overrun; в многозадачной системе это более чем вероятно. Прерыванию хотя бы можно приоритет поставить повыше.
singlskv
Цитата(mungo @ Jun 19 2008, 14:10) *
Много раз читал тут, что у людей аппаратный и-квадрат в этом камне не работает. Видел софтовые реализации.
Однажды я наткнулся на пример от атмела и сделал свою реализацию. Работает уже год без проблем.
Он как бы работает но не совсем, самая главная проблемма в работе
i2c на sam7 заключается в том, что i2c на sam7 работает практически в синхронном режиме,
те рассчитывать на то что slave может задержать транзакцию на неопределенное время не
приходиться....

то есть слейв просто должен начинать отвечать практически мгновенно...

для железок типа EEPROM это всегда выполняется...
defunct
Цитата(singlskv @ Jun 20 2008, 23:57) *
рассчитывать на то что slave может задержать транзакцию на неопределенное время не
приходиться....

В этом есть своя прелесть, меньше шансов подвесить систему слейвом. Да и нечего слейву тормозить транзакцию. Слейв должен укладываться в клок мастера, иначе - надо снижать скорость.

Собсно программный I2C (надежный как бревно) разве чем-то отличается? Тоже синхронный.
Или кто-то мониторит SCL?
aaarrr
Цитата(defunct @ Jun 21 2008, 02:52) *
Собсно программный I2C (надежный как бревно) разве чем-то отличается? Тоже синхронный.
Или кто-то мониторит SCL?

Почему-то с программным (и без мониторинга SCL) работают NXP'овские кристаллы, точнее, они почему-то не работают с аппаратным.
defunct
Цитата(aaarrr @ Jun 21 2008, 01:57) *
Почему-то с программным (и без мониторинга SCL) работают NXP'овские кристаллы, точнее, они почему-то не работают с аппаратным.

Какие именно NXP кристалы не работают? И на какой скорости?
LPC в качестве слева прекрасно связывается с SAM'овским мастером на ~100kHz.

В предыдущем посте говоря (надежный как бревно) я имел в виду действительно надежный. Вместо бревно лучше сказать "скала" - нечто большое и прочное. ;>

Цитата
самая главная проблемма в работе i2c на sam7 заключается в том, что i2c на sam7 работает практически в синхронном режиме

На мой взгляд это не проблема, и даже не фича, а то как должно быть.
Не успевает слейв, значит NACK и в сад такой слейв, и освободить шину для тех кто успевает.
aaarrr
Цитата(defunct @ Jun 21 2008, 03:06) *
Какие именно NXP кристалы не работают? И на какой скорости?

SAA7113, на любой. При этом картинка на линиях вроде бы вполне себе хорошая, да вот только слейв переодически выдает NAK.

Цитата(defunct @ Jun 21 2008, 03:06) *
Не успевает слейв, значит NACK и в сад такой слейв, и освободить шину для тех кто успевает.

Есть слейвы, которые принципиально всегда держат SCL при обращении к некоторым регистрам (TVP5150, например) - так что, в сад их всех?
defunct
Цитата(aaarrr @ Jun 21 2008, 02:10) *
SAA7113, на любой. При этом картинка на линиях вроде бы вполне себе хорошая, да вот только слейв переодически выдает NAK.

Он действительно его выдает, или так сообщает SAM'овская логика?
aaarrr
Действительно выдает.
defunct
Цитата(aaarrr @ Jun 21 2008, 02:20) *
Есть слейвы, которые принципиально всегда держат SCL при обращении к некоторым регистрам (TVP5150, например) - так что, в сад их всех?

там же есть I2C Timing Requirements
ставить подобающую скорость. (для TVPS5150 - 15kHz для тех регистров которые тормозят).

Цитата
Действительно выдает.

тогда проблема в слейве, или в уровнях линии, сами же говорите картинка на линиях вполне хорошая. Откуда появляются чудеса?

PS: я доверяю Вашему 7-ми летнему опыту работы с этими чипами, но и просто проверяю. Потому как взять вот так вот и принять на веру, что модуль недееспособен не могу.
aaarrr
Цитата(defunct @ Jun 21 2008, 03:28) *
там же есть I2C Timing Requirements
ставить подобающую скорость. (для TVPS5150 - 15kHz для тех регистров которые тормозят).

Согласитесь, что нормальный I2C-контроллер не должен вынуждать пользователя заниматься такими извращениями - ронять скорость обмена в 30 раз.

Цитата(defunct @ Jun 21 2008, 03:28) *
тогда проблема в слейве, или в уровнях линии, сами же говорите картинка на линиях вполне хорошая. Откуда появляются чудеса?

Нет, не в слейве, т.к. на софтверном I2C с теми же линиями на той же скорости все прекрасно работает.
Я не стал разбираться до конца, что же именно происходит, так как время дорого, а потрачено его было и так изрядно.
defunct
Цитата(aaarrr @ Jun 21 2008, 02:40) *
Нет, не в слейве, т.к. на софтверном I2C с теми же линиями на той же скорости все прекрасно работает.

Так сигналы на линии правильные или нет?
Пока имеем из Ваших слов:

Цитата
При этом картинка на линиях вроде бы вполне себе хорошая


Значит мастер шлет правильные сигналы?
Тогда возникает вопрос - почему же при правильных сигналах:
Цитата
да вот только слейв переодически выдает NAK. (Действительно выдает.)

?
Вопрос открытый т.к.
Цитата
Я не стал разбираться до конца, что же именно происходит, так как время дорого, а потрачено его было и так изрядно.

Понимаю. Промоделировать ситуацию с NACK'ом у меня не вышло. Предполагаю, что причина может быть связана с генерацией START'a.
А по работе с i2c слейвами с которыми работаю я, SAM'овский TWI мастер меня устраивает.

Цитата
Согласитесь, что нормальный I2C-контроллер не должен вынуждать пользователя заниматься такими извращениями - ронять скорость обмена в 30 раз.

Соглашусь, не должен. (только софтверная реализация ведь еще сильнее будет бить по производительности...). А согласитесь ли Вы, что нормальный I2C слейв не должен вынуждать мастера ждать ~100mks на ровном месте?
aaarrr
Цитата(defunct @ Jun 21 2008, 03:44) *
Так сигналы на линии правильные или нет?

На вид - да, правильные. То есть, если запустить выбор слейва в цикле (Start->Addr->Stop), то на осциллографе наблюдается стабильная картинка с периодически пропадающим ACK. И так на любой скорости.

У меня этот эффект тоже вызвал недоумение.


Цитата(defunct @ Jun 21 2008, 03:44) *
Соглашусь. Но также согласитесь, что нормальный I2C слейв не должен вынуждать мастера ждать 100mks на ровном месте.

Не соглашусь: стандарт это позволяет, значит можно smile.gif

Цитата(defunct @ Jun 21 2008, 03:44) *
Промоделировать ситуацию с NACK'ом у меня не вышло. Предполагаю, что причина может быть связана с генерацией START'a.

Нет, START вроде как не при чем. На чтении дело обстоит еще хуже: при последовательном чтении группы регистров в какой-то момент времени SAA перестает передавать данные (скорее всего ловит STOP или NACK мастера).

Цитата(defunct @ Jun 21 2008, 03:44) *
А по работе с i2c слейвами с которыми работаю я, SAM'овский TWI мастер меня устраивает.

Меня тоже почти все устраивало до времени. С ним у меня вполне нормально работали EEPROM'ы разных производителей, далласовские часы, TI'шные кодеки... Я даже готов был с пеной у рта доказывать, что все в порядке и просто надо читать еррату smile.gif А вот в последнем проекте пришлось перейти на софтварную реализацию.
defunct
Цитата(aaarrr @ Jun 21 2008, 03:16) *
На вид - да, правильные. То есть, если запустить выбор слейва в цикле (Start->Addr->Stop), то на осциллографе наблюдается стабильная картинка с периодически пропадающим ACK. И так на любой скорости.

Нет, START вроде как не при чем. На чтении дело обстоит еще хуже: при последовательном чтении группы регистров в какой-то момент времени SAA перестает передавать данные (скорее всего ловит STOP или NACK мастера).

Очень похоже на проблему фронтов/уровней сигналов.

Цитата
Не соглашусь: стандарт это позволяет, значит можно smile.gif

Если придерживаться стандарта, то в софтверной реализации надо реализовывать мониторинг SCL wink.gif
aaarrr
Цитата(defunct @ Jun 21 2008, 04:23) *
Очень похоже на проблему фронтов/уровней сигналов.

Фронты и уровни не зависят от реализации (SW/HW).

Цитата(defunct @ Jun 21 2008, 04:23) *
Если придерживаться стандарта, то в софтверной реализации надо реализовывать мониторинг SCL wink.gif

В девайсе с TVP5150 я так и сделал.
defunct
Цитата(aaarrr @ Jun 21 2008, 03:36) *
Фронты и уровни не зависят от реализации (SW/HW).

В теории. А на практике имеем NACK без причины.

Цитата
То есть, если запустить выбор слейва в цикле (Start->Addr->Stop), то на осциллографе наблюдается стабильная картинка с периодически пропадающим ACK.

Я понимаю эту фразу так - мастер выдает всегда одинаковую форму сигналов на шине. Отличие только в таймфрейме ACK от слейва. Коль так, то слейву что-то не нравится и это что-то зарыто явно не в форме сигнала (иначе бы Вы заметили нестабильность). Значит на модуль грешить нельзя - его задача дать форму и он ее дает.
aaarrr
Детально я эту форму не изучал - для этого нужно записать "убитый" цикл и внимательно просмотреть,
а цифрового осциллографа у меня под рукой не было.

А грешить мне, кроме как на модуль, больше не на что.
singlskv
Цитата(defunct @ Jun 21 2008, 02:52) *
В этом есть своя прелесть, меньше шансов подвесить систему слейвом. Да и нечего слейву тормозить транзакцию. Слейв должен укладываться в клок мастера, иначе - надо снижать скорость.

Цитата(defunct @ Jun 21 2008, 03:06) *
На мой взгляд это не проблема, и даже не фича, а то как должно быть.
Не успевает слейв, значит NACK и в сад такой слейв, и освободить шину для тех кто успевает.

Цитата(aaarrr @ Jun 21 2008, 03:20) *
Есть слейвы, которые принципиально всегда держат SCL при обращении к некоторым регистрам (TVP5150, например) - так что, в сад их всех?

Цитата(defunct @ Jun 21 2008, 03:28) *
там же есть I2C Timing Requirements
ставить подобающую скорость. (для TVPS5150 - 15kHz для тех регистров которые тормозят).

Цитата(aaarrr @ Jun 21 2008, 03:40) *
Согласитесь, что нормальный I2C-контроллер не должен вынуждать пользователя заниматься такими извращениями - ронять скорость обмена в 30 раз.

ИМХО:
- I2C статическая шина просто по определению
- попросы подвешивания шины должны решаться механизмами таймаутов как на стороне мастера
так и на стороне слейва(особенно при софтовой реализации слейва)
- исходя из статической природы I2C обязателен мониторинг SCL мастером
- снижение скорости шины(для устройств которы не готовы отвечать мгновенно) только уменьшит
пропускную способность всей шины
ИМХО, конкретный пример:
- слейв - микроконтроллер
- запрос от мастера может иметь разную длинну
- при получении запроса от мастера слейв должен чего-нить сделать(банально скопировать
запрошенные данные в буфер обмена)
- время готовности слейва зависит от типа(длинны)/сущности запроса
Цитата
Собсно программный I2C (надежный как бревно) разве чем-то отличается? Тоже синхронный.
Или кто-то мониторит SCL?

По стандарту, мониторить SCL есть прямая обязанность мастера.
defunct
Цитата(singlskv @ Jun 22 2008, 19:54) *
ИМХО:
- I2C статическая шина просто по определению
- вопросы подвешивания шины должны решаться механизмами таймаутов как на стороне мастера
так и на стороне слейва(особенно при софтовой реализации слейва)
- исходя из статической природы I2C обязателен мониторинг SCL мастером
- снижение скорости шины(для устройств которы не готовы отвечать мгновенно) только уменьшит

Наблюдал однако как LPC с его абсолютно правильным I2C модулем подвисал из-за того, что слейв передерживал SCL. И приходилось переинициализировать модуль.
Поэтому тормозные слейвы лучше сразу в сад. Природа обмена IMHO должна быть синхронной, чтобы мастер с множеством других девайсов на шине никак не зависел от конкретного одного слейва.
И я очень рад, что в SAM синхронный модуль.

Цитата
ИМХО, конкретный пример:
- слейв - микроконтроллер
- запрос от мастера может иметь разную длинну
- при получении запроса от мастера слейв должен чего-нить сделать(банально скопировать
запрошенные данные в буфер обмена)
- время готовности слейва зависит от типа(длинны)/сущности запроса


Пример не убедительный. Предложу свой протокол, который решает проблемы задержек при обмене МК-МК.
типы транзакций:
1. Команда (от мастера к слейву)
2. Ответ (от слейва к мастеру)
3. Индикатор (от слейва к мастеру)
4. Подтверждение индикатора (от мастера к слейву) по формату то же что и "1".

Теперь как это работает.
A. каждый пакет начинается байтом длины (что накладывает ограничение на длину пакета - 255)
B. от мастера к слейву - никаких проблем, мастер просто передает блок данных, слейв просто принимает и складывает по прерыванию каждый байт данных. (уж положить байт в буфер не бог весть какая задача, если программа сделана без delay_ms в обработчиках прерываний, то ACK слейв сформировать без задержек успеет).
C. По приему всего пакета слейв начинает его разбор. Столько веремени сколько нужно. Мастер в это время волен общаться с другим слейвом.

D. мастер забирает ответ слейва или индикатор (от слейва к мастеру).
- Если у слейва есть что отправить (команда выполнена есть подготовленный к отправке "ответ", или есть запрос к мастеру "индикатор"), то первым байтом слейв передает длину блока. Мастер инициализирует счетчик ожидаемых байт и продолжает прием, зная когда надо отправить NACK на последный байт.
- Если у слейва ответ не подготовлен, то он сразу шлет 0 без разбора, мастер ставит NACK, вытаскивает еще один байт данных, завершает обмен. И переходит к другому слейву.

Вот и все, все синхронно и никаких задержек.

PS: в моей системе мастер выполняет роль маршрутизатора (принимает данные с одного быстрого канала и шлет (направляет пакеты) на несколько до 64х медленных каналов, которые обслуживаются I2C слейвами mega'ми). Мастер раздает команды всем слейвам, потом забирает ответы.
aaarrr
Цитата(defunct @ Jun 29 2008, 05:43) *
Природа обмена IMHO должна быть синхронной, чтобы мастер с множеством других девайсов на шине никак не зависел от конкретного одного слейва.
И я очень рад, что в SAM синхронный модуль.

Правильно: забьем на стандарт, сделаем свой глючный и несовместимый модуль и назовем его TWI, чтобы еще и денег платить не пришлось sad.gif
Andrew Lekar
Цитата
Если придерживаться стандарта, то в софтверной реализации надо реализовывать мониторинг SCL

В девайсе с TVP5150 я так и сделал.

Я так понял, исходя из беседы, что аппаратный TWI в AT91SAMxxx глючноват, тем более применимо к TVP5150/SAA71xx. А я как раз собираюсь подключить TVP5150 к SAM9260. Рано или поздно я его конечно запущу, но чтобы не наступать на грабли, не дадите ли ссылку на приличный софтовый I2C и общих рекомендаций по стыкованию?
aaarrr
Цитата(Andrew Lekar @ Sep 10 2009, 21:40) *
Рано или поздно я его конечно запущу, но чтобы не наступать на грабли, не дадите ли ссылку на приличный софтовый I2C и общих рекомендаций по стыкованию?

Рекомендации по стыкованию есть в доках от TI, а простой софтовый I2C написать - пара-тройка часов работы.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.