Krik99 0 14 января, 2019 Опубликовано 14 января, 2019 (изменено) · Жалоба Добрый день. Есть утройство у которого на шине i2c висит 3 слейва, все в приделах одной платы. Часы, ээпром и дисплей. Так вот, основная часть логики завязана с роботой еепром. Программа довольно много обращается к еепром и иногда бывают сбои. Пишу код под Coide и готового решения AN2824 для него я не нашел. Собственно проблема в том, что если читаю 1 или 2 байта читается какой-то мусор, а если больше 3 то и вовсе виснет еепром и шина всегда занята, даже если перезагружаю i2c на контроллере. С записью проблем нет. DMA не использую так как приходится много читать для поиска пустого блока, проверку делаю "на лету" без выгрузки всего муссора с eeprom в озу. Второй день уже не могу понять в чем проблема, может чего уже не замечаю, вот код. unsigned char I2C_Read_git(I2C_TypeDef* I2Cx, unsigned char SlaveAddress, unsigned char *buf, unsigned int nbyte){ //I2C2->CR2 |= I2C_IT_ERR; //interrupts for errors // Wait for idle I2C interface if(wait_for(FLAG, I2C_FLAG_BUSY) == 0) return I2CERR; //go out with timeout error // Enable Acknowledgement, clear POS flag I2C_AcknowledgeConfig(I2Cx, ENABLE); I2C_NACKPositionConfig(I2Cx, I2C_NACKPosition_Current); // Intiate Start Sequence (wait for EV5 I2C_GenerateSTART(I2Cx, ENABLE); if(wait_for(EVENT, I2C_EVENT_MASTER_MODE_SELECT) == 0) return I2CERR; //go out with timeout error // Send Address I2C_Send7bitAddress(I2Cx, SlaveAddress, I2C_Direction_Receiver); // EV6 if(wait_for(FLAG, I2C_FLAG_ADDR) == 0) return I2CERR; //go out with timeout error if(nbyte == 1){ // Clear Ack bit I2C_AcknowledgeConfig(I2Cx, DISABLE); // EV6_1 -- must be atomic -- Clear ADDR, generate STOP __disable_irq(); (void) I2Cx->SR2; I2C_GenerateSTOP(I2Cx,ENABLE); __enable_irq(); // Receive data EV7 if(wait_for(FLAG, I2C_FLAG_RXNE) == 0) return I2CERR; //go out with timeout error *buf++ = I2C_ReceiveData(I2Cx); }else if(nbyte == 2){ // Set POS flag I2C_NACKPositionConfig(I2Cx, I2C_NACKPosition_Next); // EV6_1 -- must be atomic and in this order __disable_irq(); (void) I2Cx->SR2; // Clear ADDR flag I2C_AcknowledgeConfig(I2Cx, DISABLE); // Clear Ack bit __enable_irq(); // EV7_3 -- Wait for BTF, program stop, read data twice if(wait_for(FLAG, I2C_FLAG_BTF) == 0) return I2CERR; //go out with timeout error __disable_irq(); I2C_GenerateSTOP(I2Cx,ENABLE); *buf++ = I2C_ReceiveData(I2Cx); __enable_irq(); *buf++ = I2C_ReceiveData(I2Cx); I2C_NACKPositionConfig(I2Cx, I2C_NACKPosition_Current); }else{ (void) I2Cx->SR2; // Clear ADDR flag while (nbyte-- != 3){ // EV7 -- cannot guarantee 1 transfer completion time, wait for BTF // instead of RXNE if(wait_for(FLAG, I2C_FLAG_BTF) == 0) return I2CERR; //go out with timeout error *buf++ = I2C_ReceiveData(I2Cx); } if(wait_for(FLAG, I2C_FLAG_BTF) == 0) return I2CERR; //go out with timeout error // EV7_2 -- Figure 1 has an error, doesn't read N-2 ! I2C_AcknowledgeConfig(I2Cx, DISABLE); // clear ack bit __disable_irq(); I2C_GenerateSTOP(I2Cx,ENABLE); // program stop *buf++ = I2C_ReceiveData(I2Cx); // receive byte N-2 __enable_irq(); // wait for byte N if(wait_for(EVENT, I2C_EVENT_MASTER_BYTE_RECEIVED) == 0) return I2CERR; //go out with timeout error *buf++ = I2C_ReceiveData(I2Cx); // receive byte N-1 nbyte = 0; } // Wait for stop if(wait_for(FLAG, I2C_FLAG_STOPF) == 0) return I2CERR; //go out with timeout error I2C_AcknowledgeConfig(I2Cx, ENABLE); return I2COK; } unsigned char EEPROM_Read(unsigned int addr, unsigned char *data, unsigned char len){ unsigned char y=0; // While the bus is busy if(wait_for(FLAG, I2C_FLAG_BUSY) == 0) return I2CERR; //go out with timeout error I2C_AcknowledgeConfig(I2C2, ENABLE); // Generate the Start Condition I2C_GenerateSTART(I2C2, ENABLE); if(wait_for(EVENT, I2C_EVENT_MASTER_MODE_SELECT) == 0) return I2CERR; //go out with timeout error I2C_Send7bitAddress(I2C2, 0xA0, I2C_Direction_Transmitter); //send adress chip if(wait_for(EVENT, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED) == 0) return I2CERR; //go out with timeout error I2C_SendData(I2C2, addr>>8); //send upper bit if(wait_for(EVENT, I2C_EVENT_MASTER_BYTE_TRANSMITTED) == 0) return I2CERR; //go out with timeout error I2C_SendData(I2C2, addr & 0xFF); //send lower bit if(wait_for(EVENT, I2C_EVENT_MASTER_BYTE_TRANSMITTED) == 0) return I2CERR; //go out with timeout error I2C_GenerateSTOP(I2C2, ENABLE); if(wait_for(FLAG, I2C_FLAG_BUSY) == 0) return I2CERR; //go out with timeout error y=I2C_Read_git(I2C2, 0xA0, data, len); return y; } А вот код который работает, но здесь нет всех замечаний которые были написаны в AN2824 о глючном i2c в stm32f1: unsigned char EEPROM_Read(unsigned int addr, unsigned char *data, unsigned char len){ unsigned int i; // While the bus is busy if(wait_for(FLAG, I2C_FLAG_BUSY) == 0) return I2CERR; //go out with timeout error I2C_AcknowledgeConfig(I2C2, ENABLE); // Generate the Start Condition I2C_GenerateSTART(I2C2, ENABLE); if(wait_for(EVENT, I2C_EVENT_MASTER_MODE_SELECT) == 0) return I2CERR; //go out with timeout error I2C_Send7bitAddress(I2C2, 0xA0, I2C_Direction_Transmitter); //send adress chip if(wait_for(EVENT, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED) == 0) return I2CERR; //go out with timeout error I2C_SendData(I2C2, addr>>8); //send upper bit if(wait_for(EVENT, I2C_EVENT_MASTER_BYTE_TRANSMITTED) == 0) return I2CERR; //go out with timeout error I2C_SendData(I2C2, addr & 0xFF); //send lower bit if(wait_for(EVENT, I2C_EVENT_MASTER_BYTE_TRANSMITTED) == 0) return I2CERR; //go out with timeout error I2C_GenerateSTOP(I2C2, ENABLE); if(wait_for(FLAG, I2C_FLAG_BUSY) == 0) return I2CERR; //go out with timeout error I2C_GenerateSTART(I2C2, ENABLE); // Generate the Start Condition if(wait_for(EVENT, I2C_EVENT_MASTER_MODE_SELECT) == 0) return I2CERR; //go out with timeout error I2C_Send7bitAddress(I2C2, 0xA0, I2C_Direction_Receiver); //send adress chip if(wait_for(EVENT, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED) == 0) return I2CERR; //go out with timeout error for(i = 0; i<len; i++){ if(i<len-1){ if(wait_for(EVENT, I2C_EVENT_MASTER_BYTE_RECEIVED) == 0) return I2CERR; //go out with timeout error }else{ I2C_AcknowledgeConfig(I2C2, DISABLE); // Prepare an NACK for the next data received if(wait_for(EVENT, I2C_EVENT_MASTER_BYTE_RECEIVED) == 0) return I2CERR; //go out with timeout error I2C_GenerateSTOP(I2C2, ENABLE); } *data = I2C_ReceiveData(I2C2); data++; } if(wait_for(FLAG,I2C_FLAG_STOPF)==0) return I2CERR; I2C_AcknowledgeConfig(I2C2, ENABLE); //Delay_ms(5); return I2COK; } За ранние спасибо. Изменено 14 января, 2019 пользователем Krik99 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
haker_fox 60 15 января, 2019 Опубликовано 15 января, 2019 · Жалоба Ну то, что можно порекомендовать без привязки к конкретному микроконтроллеру, так это подключить осциллограф, и посмотреть форму сигналов на шине. А затем, если с ней всё в порядке, можно поглядеть, что с данными. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Krik99 0 15 января, 2019 Опубликовано 15 января, 2019 (изменено) · Жалоба 5 hours ago, haker_fox said: Ну то, что можно порекомендовать без привязки к конкретному микроконтроллеру, так это подключить осциллограф, и посмотреть форму сигналов на шине. А затем, если с ней всё в порядке, можно поглядеть, что с данными. Конкретный контроллер Stm32f103rbt6. Но на сколько я понял с AN2824 i2c у них у всех глючный. Ок, как будет доступ к осциллографу сделаю скрины Изменено 15 января, 2019 пользователем Krik99 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
haker_fox 60 15 января, 2019 Опубликовано 15 января, 2019 · Жалоба 11 minutes ago, Krik99 said: i2c у них у всех глючный что это значит? Возможно в errata есть какая-то полезная информация. Возможно придётся всё отлаживать по-шагово, проверяя выполнение всех условий на шине (START, STOP, ACK, NACK) и т.п. Ну и снова повторюсь, лучше попробовать написать свой драйвер. Пусть медленно, зато знакомый до каждого угла) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Integro 0 15 января, 2019 Опубликовано 15 января, 2019 · Жалоба 20 hours ago, Krik99 said: а если больше 3 то и вовсе виснет еепром и шина всегда занята, даже если перезагружаю i2c на контроллере В данном случае висит один из слейвов, вероятно eeprom, нужно в ручную(gpio) клочить и ждать пока этот слейв отпустить линию SDA, либо дернуть питание слейвам, если это конечно возможно и позволяет ситуация. В I2C_Read_git точно должно быть 3? while (nbyte-- != 3){ Я сейчас не уверен, но мне кажется Вы один байт потеряете, могу ошибаться. Сложно код читается... Вообще, стремно выглядит этот I2C_Read_git... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
haker_fox 60 15 января, 2019 Опубликовано 15 января, 2019 · Жалоба 8 minutes ago, Integro said: вероятно eeprom, нужно в ручную(gpio) клочить В своё время я где-тона просторах сети встречало документ, в котором рекомедовалось при инициализации шины подать клок не менее 30 тактов на SCL. Что должно быть при этом с SDA я не помню. И только после этого можно было начинать работу. Вообще такое мне ни разу не понадобилось. Ассортимент микросхем с которыми я работал на этой шине не очень широк, но всё же: pca9534, ds1682, рахные часы, разные цифрорезисторы. И все они нормально работали сразу. Но вот с tsc2007 (контроллер резистивного тач-скрина) в нескольких приборах была проблема: он просто иногда (редко) при включении прибора не работал. Не отвечал. Логический анализатор показывал, что к микросхеме стучаться правильно. Не выручили и хололстые клоки на SCL. А вот передёргивание питания - выручило. Допускаю, что мы могли накосячить со схемотехникой, хотя где там можно ошибиться, я не знаю. Мы для этого приспособили полевичок на питании микросхемы, и просто при включении прибора включаем микросхему после инициализации шины. Работает надёжно. С первопричиной же пробовали разобраться, так и не вышло. В документации ничего на этот счёт не сказано. На форумах тоже тишина. В другом приборе на линуксе такой проблемы, похоже, нет. Но там драйвер этой микросхемы подробно никто не смотрел. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Integro 0 16 января, 2019 Опубликовано 16 января, 2019 · Жалоба 17 hours ago, haker_fox said: Ассортимент микросхем с которыми я работал на этой шине не очень широк От сюда следствие... 17 hours ago, haker_fox said: Вообще такое мне ни разу не понадобилось. Не понимаю для каких целей Вы нам это написали... 17 hours ago, haker_fox said: он просто иногда (редко) при включении прибора не работал. А вот это не нормально, я бы грешил на ошибку в схемотехнике(проблемы с качесвом питания) или не соблюдение рекомендуемых Power-On\Reset timings Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
haker_fox 60 16 января, 2019 Опубликовано 16 января, 2019 · Жалоба 10 minutes ago, Integro said: Не понимаю для каких целей Вы нам это написали... А что, чтобы делиться своим опытом, я должен разрешение спрашивать? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Integro 0 16 января, 2019 Опубликовано 16 января, 2019 · Жалоба 5 minutes ago, haker_fox said: чтобы делиться своим опытом 17 hours ago, haker_fox said: Ассортимент микросхем с которыми я работал на этой шине не очень широк, Так Вы ведь написали что опыта у Вас как такового нет. Простите если задел. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
haker_fox 60 16 января, 2019 Опубликовано 16 января, 2019 · Жалоба 1 minute ago, Integro said: Так Вы ведь написали что опыта у Вас как такового нет. Я написал, что ассортимент микросхем не очень широк. С опытом это прямо не связано. Ну да, ещё, конечно же, забыл упомянуть разномастную память, начиная от 24c02, заканчивая какими-то современными от микрочип EEPROM (названия не помню). Но разве это меняет суть? Подход-то одинаковый. И про документ я написал. Я вообще сейчас заметил, что здесь обращался не к автору темы. Перепутал. 4 minutes ago, Integro said: Простите если задел. Всё нормально, я искренне удивился. Тема-то для начинающих. Я и подумал. что автору будет полезен мой скромный опыт. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Krik99 0 12 марта, 2019 Опубликовано 12 марта, 2019 (изменено) · Жалоба deleted Изменено 12 марта, 2019 пользователем Krik99 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться