Метценгерштейн 0 6 октября, 2016 Опубликовано 6 октября, 2016 · Жалоба STM32 подключен слейвом к другому процу АРМ на Линуксе. Все работает, но поведение странное. Периодически отваливается шина I2C и мой STM не получает никакие команды из вне. Написана на регистрах инициализация. Подтяжки шины к +3,3 по 7,5 К. Куда можно смотреть? Может что не проинициализировал в МК? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Jury093 2 6 октября, 2016 Опубликовано 6 октября, 2016 · Жалоба Куда можно смотреть? Может что не проинициализировал в МК? так проведите диагностику с логированием как на стороне линукса - диагностический выхлоп драйвера i2c в syslog так и стороне stm32, желательно вывод транзакций с записью с консоли + дамп статусных регистров ну и осцилл на шину смотрите работу, фиксируете, возник дефект - изучаете картину, ловите виновного.. может слейв NAK глотает, может тайминги не держит, может машина состояния что-то не формирует Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Метценгерштейн 0 6 октября, 2016 Опубликовано 6 октября, 2016 · Жалоба так проведите диагностику с логированием как на стороне линукса - диагностический выхлоп драйвера i2c в syslog так и стороне stm32, желательно вывод транзакций с записью с консоли + дамп статусных регистров ну и осцилл на шину смотрите работу, фиксируете, возник дефект - изучаете картину, ловите виновного.. может слейв NAK глотает, может тайминги не держит, может машина состояния что-то не формирует что значит, NAK глотает? А если тайминги не держит - что значит? Как смотреть? Логгирование в Линуксе I2C как запустить? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
gerber 7 6 октября, 2016 Опубликовано 6 октября, 2016 · Жалоба Изъездил аппаратный I2C Slave на STM32 вдоль и поперек. Сталкивался с тем, что иногда I2C Slave ловит ложное STOP-условие, то есть перепад Low->High на SDA при высоком SCL. Это может происходить, когда мастер меняет SDA близко к фронтам SCL, и учитывая емкостные свойства линий SCL/SDA, аппаратный контроллер фиксирует STOP-условие посреди посылки, что приводит к установке бита 8 (BERR - Bus Error, Misplaced Start or Stop condition) в регистре статуса. Посылка при этом, естественно, теряется, и конечный автомат ждёт снова START-условия, адреса и т. п. Поэтому, задействуя аппаратный контроллер I2C, необходимо включать прерывания по ошибочным состояниям и корректно обрабатывать их. Самое печальное в этом то, что отключить такое поведение (отслеживание Bus Error) нельзя, и это очень мешает нормальной работе, особенно в приложениях, где мастер "не любит" повторять запросы, и при неответе слейва тупо фиксирует ошибку. Что касается меня, то я, изрядно повозившись с аппаратным I2C Slave на STM32, переписал драйвер таким образом, что аппаратный I2C делает для меня только START+сравнение адреса, после чего "будит" контроллер прерыванием "Address matched", после чего ноги переназначаются на GPIO, и дальнейшая работа идёт софтовой эмуляцией I2C Slave. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Метценгерштейн 0 6 октября, 2016 Опубликовано 6 октября, 2016 · Жалоба выложу инициализацию I2C. Может у кого глаз зацепится за что-то некорректное. Проц STM32F030 На всякий случай сейчас еще раз перевыкачал CubeMX, так с ним шину I2C Линукс даже не сканирует. Сразу глючит. HAL вообще здесь не применим. void init(void) { i2c.max_rx_count = sizeof(incoming); i2c.state = st_idle; uint_fast32_t bus_clk; uint_fast32_t scale; static const struct gpio_configuration pinconf = { .open_drain=1, .output=0, .analog=0, .alter=1, .speed=0, .pullup=0, // было 1 .pulldn=0, .altfunc = 1, // convenient i2c .lock=0 }; RCC->AHBENR |= RCC_AHBENR_GPIOBEN; gpio_pin_conf(GPIOB, 6,1,&pinconf); gpio_pin_conf(GPIOB, 7,1,&pinconf); RCC->APB1RSTR |= RCC_APB1RSTR_I2C1RST; RCC->APB1RSTR ^= RCC_APB1RSTR_I2C1RST; RCC->APB1ENR |= RCC_APB1ENR_I2C1EN; SystemCoreClockUpdate(); // get sysclk for apb1 if((RCC->CFGR3 & RCC_CFGR3_I2C1SW) == 0) // RCC_CFGR3_I2C1SW если 1, то от SystemCoreClock { bus_clk = HSI_VALUE; } else { bus_clk = SystemCoreClock; if(RCC->CFGR & RCC_CFGR_PPRE_2) { uint_fast32_t factor = RCC->CFGR & (RCC_CFGR_PPRE_0 | RCC_CFGR_PPRE_1); if(factor & RCC_CFGR_PPRE_0) factor |= 1; if(factor & RCC_CFGR_PPRE_1) factor |= 2; factor &= 3; bus_clk >>= factor + 1; } } // general scale factor to 8mhz scale = bus_clk / (HSI_VALUE/2); scale -= 1; scale &= 0x0f; myI2C->TIMINGR = scale << 28; // tclk = 250ns refman page 556 - place config from table 100khz myI2C->TIMINGR |= 0x13 //scll | (0x0f << 8) //sclh | (0x02 << 16) //sdadel | (0x04 << 20); // scldel //conf i2c NVIC_EnableIRQ(I2C1_IRQn); //set int mask myI2C->CR1 = I2C_CR1_ADDRIE | I2C_CR1_RXIE | I2C_CR1_TXIE //| I2C_CR1_NACKIE | I2C_CR1_STOPIE | I2C_CR1_TCIE | I2C_CR1_ERRIE; // enable analog noise filtering or digital // myI2C->CR1 |= I2C_CR1_ANFOFF;// currently analog // clock stretch enabled // set own address myI2C->OAR1 = I2C_OAR1_OA1EN | ((get_slave_address() & 0x7F) << 1); // enable myI2C->CR1 |= I2C_CR1_PE; } void gpio_pin_conf( GPIO_TypeDef *gp, uint8_t num, uint8_t value, const struct gpio_configuration *conf) { volatile uint32_t *altreg; uint32_t msk2 = 1 << (num*2); uint32_t msk4 = 1 << ((num & 0x07)*4); num &= 0x0f; gp->MODER &= ~(3*msk2); if(conf->output) gp->MODER |= msk2; if(conf->analog) gp->MODER |= 3*msk2; if(conf->alter) gp->MODER |= 2*msk2; if(conf->open_drain) gp->OTYPER |= 1 << num; else gp->OTYPER &= ~(1 << num); gp->OSPEEDR &= ~(3*msk2); gp->OSPEEDR |= conf->speed * msk2; gp->PUPDR &= ~(3*msk2); if(conf->pullup) gp->PUPDR |= msk2; if(conf->pulldn) gp->PUPDR |= 2*msk2; //set value gp->BSRR |= 1 << (num + value?0:16); //set af altreg = &gp->AFR[(num >= 8)]; *altreg &= ~(0x0F * msk4); *altreg |= conf->altfunc * msk4; } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
gerber 7 6 октября, 2016 Опубликовано 6 октября, 2016 (изменено) · Жалоба Как по мне, сбрасывать периферию, не включив её клок, бессмысленно, она "мертва". Последовательность инициализации несколько напрягает - сначала нужно включать клок, потом инитить и включать периферию, только потом конфигурировать "ноги", и уже в самом конце разрешать от неё прерывания. При нарушении такой последовательности возможны всяки-разны казусы, типа невовремя стрельнувшего прерывания и т. п. Хотя это всё мелочи и придирки, в общем-то. :laughing: Ах, да, ещё I2C Slave не нуждается в делителях клока, это всё нужно только мастеру. Slave работает на том клоке SCL, который приходит от мастера. Изменено 6 октября, 2016 пользователем gerber Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Метценгерштейн 0 6 октября, 2016 Опубликовано 6 октября, 2016 · Жалоба ну а так в целом- все регистры проинициализированы корректно? Или чего-то забыто? Как по мне, сбрасывать периферию, не включив её клок, бессмысленно, она "мертва". Последовательность инициализации несколько напрягает - сначала нужно включать клок, потом инитить и включать периферию, только потом конфигурировать "ноги", и уже в самом конце разрешать от неё прерывания. При нарушении такой последовательности возможны всяки-разны казусы, типа невовремя стрельнувшего прерывания и т. п. Хотя это всё мелочи и придирки, в общем-то. :laughing: Ах, да, ещё I2C Slave не нуждается в делителях клока, это всё нужно только мастеру. Slave работает на том клоке SCL, который приходит от мастера. не понял по включению клока: RCC->AHBENR |= RCC_AHBENR_GPIOBEN; вот включил клок, только потом дальше начинаю инициализировать регистры. Не так? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
gerber 7 6 октября, 2016 Опубликовано 6 октября, 2016 · Жалоба ну а так в целом- все регистры проинициализированы корректно? Или чего-то забыто? В целом, вроде ОК. не понял по включению клока: RCC->AHBENR |= RCC_AHBENR_GPIOBEN; вот включил клок, только потом дальше начинаю инициализировать регистры. Не так? Это клок GPIOB, имелся в виду клок I2C-контроллера RCC->APB1ENR |= RCC_APB1ENR_I2C1EN; да, его надо включать в самом начале инициализации, даже до сброса периферии, КМК. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Метценгерштейн 0 6 октября, 2016 Опубликовано 6 октября, 2016 · Жалоба RCC->AHBENR |= RCC_AHBENR_GPIOBEN; RCC->APB1ENR |= RCC_APB1ENR_I2C1EN; gpio_pin_conf(GPIOB, 6,1,&pinconf); gpio_pin_conf(GPIOB, 7,1,&pinconf); RCC->APB1RSTR |= RCC_APB1RSTR_I2C1RST; RCC->APB1RSTR ^= RCC_APB1RSTR_I2C1RST; так пойдет? Здесь мы ловим всех блох, которые глючат. Поэтому любое, что режет глаз- будем править. Насчет делителя для мастера- можно его не трогать? Я понял, что это просто лишнее написано и не применяется, но не мешает слейву моему. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
gerber 7 6 октября, 2016 Опубликовано 6 октября, 2016 · Жалоба так пойдет? Я бы снес инициализацию ног после инициализации I2C, хотя это и непринципиально, возможно. Дело вкуса, но подключать неинициализированный I2C к реальной шине, а потом его инициализировать, ИМХО, не очень правильно. Насчет делителя для мастера- можно его не трогать? Я понял, что это просто лишнее написано и не применяется, но не мешает слейву моему. Да, это не мешает слейву, просто лишняя операция. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Метценгерштейн 0 6 октября, 2016 Опубликовано 6 октября, 2016 · Жалоба Я бы снес инициализацию ног после инициализации I2C, хотя это и непринципиально, возможно. Дело вкуса, но подключать неинициализированный I2C к реальной шине, а потом его инициализировать, ИМХО, не очень правильно. Не очень понял- как предлагаете сделать? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
gerber 7 6 октября, 2016 Опубликовано 6 октября, 2016 · Жалоба Не очень понял- как предлагаете сделать? myI2C->CR1 |= I2C_CR1_PE; потом gpio_pin_conf(GPIOB, 6,1,&pinconf); gpio_pin_conf(GPIOB, 7,1,&pinconf); и лишь потом NVIC_EnableIRQ(I2C1_IRQn); Но, повторюсь, это всё дело вкуса, и вряд ли решит вопрос стабильности работы I2C. ИМХО, аппаратный I2C Slave в STM32 пригоден для работы лишь с идеальным I2C-мастером, соблюдающим "километровые" тайминги, и не переключающим SDA вблизи фронтов SCL. Вблизи - это на расстоянии менее 2-3 мкс. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Метценгерштейн 0 6 октября, 2016 Опубликовано 6 октября, 2016 · Жалоба Можно как-то попросить поделиться драйвером вашим? Пока что стоит на прогоне плата у меня- ничего не вылетает. Может просто помыл грязь перед этим. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
k155la3 26 6 октября, 2016 Опубликовано 6 октября, 2016 · Жалоба STM32 подключен слейвом к другому процу АРМ на Линуксе. Все работает, но поведение странное. Периодически отваливается шина I2C и мой STM не получает никакие команды из вне. Написана на регистрах инициализация. Подтяжки шины к +3,3 по 7,5 К. Куда можно смотреть? Может что не проинициализировал в МК? Подтяжки шины к +3,3 по 7,5 К. - нормальные, но все равно посмотрите осцилграфом форму фронтов (SDA-SCL). Мало ли что могло затянуть. Захват данных идет по фронту. Если поплыло - на осцилографе будет видно. На скорости 300 kHz у меня работает нормально на 10к. В чем проявляется "отваливание" ? Я свой колхоз с I2C HAL (MSP430) отлаживал с активным использованием лог. анализатора. Сильно рекомендую. Ваш проект "slave" - а он, на мой взгляд существенно сложнее master. Особенно обратите внимание на ACK - NACK квитирование. Если не соотв-ет протоколу I2C и slave отработал не корректно (по логике протокола) то можно войти в ступор. Например вход в режим "ожидания готовности slave". А слейв это сделал "не в том смысле", или наоборот, не сделал. Как альтернативный вариант. Может ошибка в мастере ? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Метценгерштейн 0 6 октября, 2016 Опубликовано 6 октября, 2016 · Жалоба на ночь оставлю на прогоне девайс- посмотрим к утру. Правки внес, что gerber предложил. Еще убрал внутреннюю подтяжку программную .pullup=0, // было 1 0 выставил. Мастер- это Линукс. Должно быть все отлажено. Проц на линуксе, в смысле. Посмотрим утром. Отпишусь. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться