drcepera 0 10 июля, 2013 Опубликовано 10 июля, 2013 · Жалоба Тээк.. Если прерывание разрешено в таймере (бит Update interrupt flag), плюс не запрещены прерывания в целом (PRIMASK = 0), следовательно дело может быть в запрете в NVIC? Или я еще что-то упускаю? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Артём__ 0 10 июля, 2013 Опубликовано 10 июля, 2013 · Жалоба Если прерывание разрешено в таймере (бит Update interrupt flag), плюс не запрещены прерывания в целом (PRIMASK = 0), следовательно дело может быть в запрете в NVIC? Нужно вызвать функцию разрешения прерывания в NVIC: NVIC_EnableIRQ(Номер прерывания таймера); Или я еще что-то упускаю? Тактирование таймера включено? Нужные флаги в статусе устанавливаются? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
drcepera 0 10 июля, 2013 Опубликовано 10 июля, 2013 · Жалоба Нужно вызвать функцию разрешения прерывания в NVIC: NVIC_EnableIRQ(Номер прерывания таймера); Тактирование таймера включено? Нужные флаги в статусе устанавливаются? Товарищи, таймер-то включен и NVIC именно так и проинициализирован, и прерывания происходят. КРОМЕ случая зависания в указанном месте CPAL. Более того, если при этом я разорву линию I2C - программа выйдет из этого цикла, т.к. __CPAL_I2C_HAL_GET_BUSY(pDevInitStruct->CPAL_Dev) возвращает 0 - и дальше программа будет продолжать работать хорошо, в смысле, прерывания таймеров возобновятся. Так определите, кто (где, почему) запретил прерывание, если оно не вызывается. Вот я и спрашиваю, если в регистрах таймера все в порядке и не запрещены прерывания - то дело может быть в запрете прерывания в NVIC, либо же еще в чем-нибудь? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
lotor 0 10 июля, 2013 Опубликовано 10 июля, 2013 · Жалоба то дело может быть в запрете прерывания в NVIC, либо же еще в чем-нибудь? Чудес не бывает. Когда снова "зависните" - проанализируйте отладчиком регистры, NVIC в том числе. Может, например, Вы в обработчике прерывания забываете сбрасывать pending бит события таймера или что-то в этом роде. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
esaulenka 7 10 июля, 2013 Опубликовано 10 июля, 2013 · Жалоба Мастер определяет, сколько читать/писать. Если у ведомого запросить больше, чем он может дать, он выставит NACK. Я извиняюсь за некропостинг, но это не так. Если у ведомого запросить больше, он может вообще ничего не делать - посылает подтверждения (или неподтверждения) приёмник, т.е. мастер. В этом случае мы получим много-много FF-ов, если слейв-передатчик отпустит шину вообще. Его дело - правильно подтвердить посылку с собственным адресом, и всё. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
drcepera 0 19 июля, 2013 Опубликовано 19 июля, 2013 · Жалоба OMG.. Извиняюсь, товарищи. Нашел таки косяк ) Датчик читался по таймеру А, а таймауты отслеживались по таймеру В. Хоть приоритет у В был и выше, чем А, они были в одной группе. Установил NVIC_PriorityGroup_2 - все, кажется, Ок. Не учел, что прерывания из одной группы не обрывают друг друга. Спасибо всем за ответы! ) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Ruslan-maniak 0 25 февраля, 2014 Опубликовано 25 февраля, 2014 · Жалоба Хочу поднять эту тему. Пытаюсь завести I2C через CPAL вместе с freeRTOSом. Подскажите как в cpal_conf.h замутить таймер через vApplicationTickHook(), который у меня отсчитывает миллисекунды. Я так полагаю это делается В от здесь. Но как правильно это дело задефайнить не догоняю. /* -- Section 4 : **** Configure Timeout method, TimeoutCallback **** Description: This section allows you to implement your own Timeout Procedure. By default Timeout procedure is implemented with Systick timer and CPAL_I2C_TIMEOUT_Manager is defined as SysTick_Handler. */ #define _CPAL_TIMEOUT_INIT() SysTick_Config((SystemCoreClock / 1000));\ NVIC_SetPriority (SysTick_IRQn, 0) /*<! Configure and enable the systick timer to generate an interrupt when counter value reaches 0. In the Systick interrupt handler the Timeout Error function is called. Time base is 1 ms */ #define _CPAL_TIMEOUT_DEINIT() SysTick->CTRL = 0 /*<! Disable the systick timer */ #define CPAL_I2C_TIMEOUT_Manager SysTick_Handler /*<! This callback is used to handle Timeout error. When a timeout occurs CPAL_TIMEOUT_UserCallback is called to handle this error */ #ifndef CPAL_I2C_TIMEOUT_Manager void CPAL_I2C_TIMEOUT_Manager(void); #else void SysTick_Handler(void); #endif /* CPAL_I2C_TIMEOUT_Manager */ /*#define CPAL_TIMEOUT_UserCallback (void)*/ /*<! Comment this line and implement the callback body in your application in order to use the Timeout Callback. It is strongly advised to implement this callback, since it is the only way to manage timeout errors. */ В общем основной вопрос как прикрутить к CPAL свой собственный таймер. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
kan35 7 26 февраля, 2014 Опубликовано 26 февраля, 2014 · Жалоба Я убрал всю инициализацию таймеров в CPAL (закомментив тело вами показанных макросов) #define _CPAL_TIMEOUT_INIT() /*SysTick_Config((SystemCoreClock / 1000));\ NVIC_SetPriority (SysTick_IRQn, 0) */ /*<! Configure and enable the systick timer to generate an interrupt when counter value reaches 0. In the Systick interrupt handler the Timeout Error function is called. Time base is 1 ms */ #define _CPAL_TIMEOUT_DEINIT() /*SysTick->CTRL = 0*/ /*<! Disable the systick timer */ /*#define CPAL_I2C_TIMEOUT_Manager SysTick_Handler*/ /*<! This callback is used to handle Timeout error. When a timeout occurs CPAL_TIMEOUT_UserCallback is called to handle this error */ /*#define CPAL_TIMEOUT_UserCallback (void) */ /*<! Comment this line and implement the callback body in your application in order to use the Timeout Callback. It is strongly advised to implement this callback, since it is the only way to manage timeout errors. */ и сделал так: void SysTick_Handler(void) { xPortSysTickHandler(); CPAL_I2C_TIMEOUT_Manager(); } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Ruslan-maniak 0 27 февраля, 2014 Опубликовано 27 февраля, 2014 · Жалоба Понятно. Спасибо. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Ruslan-maniak 0 27 февраля, 2014 Опубликовано 27 февраля, 2014 (изменено) · Жалоба А ещё такой вопрос, не касающийся CPAL: может ли быть такое что используя стандартную библиотеку STM в режиме Мастер не отпускает линию что бы принять ACK от слэйва после отправки адреса устройства? Просто некоторое время slave нормально отвечал, затем я немного решил порефакторить код и всё сломалось. Вернул на место, всё равно ничего не работает. Смотрю по осцилограмме - слэйв не отправляет ACK. Хотя в его работе вообще ничего меняться не должно было. Выкладываю код: Инициализация: //Инициализация GPIO RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE); GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStruct.GPIO_OType = GPIO_OType_OD; GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL; // SCL пин GPIO_InitStruct.GPIO_Pin = I2C1_SCL_PIN; GPIO_Init(I2C1_SCL_PORT, &GPIO_InitStruct); GPIO_PinAFConfig(I2C1_SCL_PORT, I2C1_SCL_PIN_SOURCE, GPIO_AF_I2C1); // SDA пин GPIO_InitStruct.GPIO_Pin = I2C1_SDA_PIN; GPIO_Init(I2C1_SDA_PORT, &GPIO_InitStruct); GPIO_PinAFConfig(I2C1_SDA_PORT, I2C1_SDA_PIN_SOURCE, GPIO_AF_I2C1); // Конфигурация I2C RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE); I2C_Cmd(I2C1, DISABLE); I2C_DeInit(I2C1); I2C_InitStruct.I2C_Mode = I2C_Mode_I2C; I2C_InitStruct.I2C_DutyCycle = I2C_DutyCycle_2; I2C_InitStruct.I2C_OwnAddress1 = I2C1_OWN_ADDRESS; I2C_InitStruct.I2C_Ack = I2C_Ack_Enable; I2C_InitStruct.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; I2C_InitStruct.I2C_ClockSpeed = I2C_SPEED; I2C_Init(I2C1, &I2C_InitStruct); // Включение интерфейса I2C_Cmd(I2C1, ENABLE); чтение регистра // Проверка готовности линии while(I2C_GetFlagStatus(I2Cx, I2C_FLAG_BUSY)); // Генерация первого старта I2C_GenerateSTART(I2Cx, ENABLE); // Проверка что линия свободна while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT)); // Отправка адреса подчинённого устройства (запись) I2C_Send7bitAddress(I2Cx, slaveAddress, I2C_Direction_Transmitter); // Проверка ACK от подчинённого устройства (есть ли такой адрес на шине) while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)); // Отправка адреса регистра чтения I2C_SendData(I2Cx, regAddress); // Проверка ACK от подчинённого устройства while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED)); // Генерация повторного старта I2C_GenerateSTART(I2Cx, ENABLE); // Проверка что линия свободна while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT)); // Отправка адреса подчинённого устройства (чтение) I2C_Send7bitAddress(I2Cx, slaveAddress, I2C_Direction_Receiver); // Проверка ACK от подчинённого устройства while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)); // Завершаем приём I2C_AcknowledgeConfig(I2Cx, DISABLE); // Проверка что байт принят (данные загружены в регистр DR) while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_RECEIVED)); // Генерируем стоп I2C_GenerateSTOP(I2C1, ENABLE); return I2C_ReceiveData(I2Cx); И после первой отправки адреса устройства ACK я так и не дожидаюсь. Устройство STA381BWS. Добавил к коду сдвиг адреса Slave'а на один бит влево. Ничего не изменилось. Изменено 28 февраля, 2014 пользователем Ruslan-maniak [codebox] для длинного кода, [code] - для короткого!!! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
BALDA 0 11 декабря, 2018 Опубликовано 11 декабря, 2018 · Жалоба Коллеги, поделитесь опытом кто как восстанавливает работу I2C (STM32f407)? После получения status HAL Timeout, иногда наблюдаю выставленный флаг BUSY причем стереть его не представляется возможным. Передергивание (PE) не помогает. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
scifi 1 11 декабря, 2018 Опубликовано 11 декабря, 2018 · Жалоба 14 minutes ago, BALDA said: Передергивание (PE) не помогает. Сброс блока точно поможет. Как-то так: RCC->APB1RSTR |= RCC_APB1RSTR_I2C1_RST; // wait a few cycles RCC->APB1RSTR &= ~RCC_APB1RSTR_I2C1_RST; Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
VladislavS 39 12 декабря, 2018 Опубликовано 12 декабря, 2018 · Жалоба Ещё заметил, что сильно уменьшает количество "подвисонов" вот такой сброс перед конфигурированием. I2C1->CR1 = I2C_CR1_SWRST; I2C1->CR1 = 0; Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Integro 0 12 декабря, 2018 Опубликовано 12 декабря, 2018 · Жалоба 14 hours ago, scifi said: Сброс блока точно поможет Как показывает практика, подвиcает не блок микроконтроллера, а один из slave'вов держит линию данных в нуле. Лечится ручным дерганьем клока, или генерацией старт-стопов пока SDA не придет в норму. Но и ресет I2C я тоже в этих случаях добавляю. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 190 12 декабря, 2018 Опубликовано 12 декабря, 2018 · Жалоба Я делал так, как рекомендует сам разработчик интерфейса (NXP). 1. При обнаружении зависания линии отменяю транзакции по этой шине. 2. Выключаю модуль I2C, деактивирую и перенастраиваю GPIO на режим ручного управления без изменения типа выходных драйверов. 3. Даю больше 9 стробов по линии SCL. 4. Выключаю синхронизацию модуля I2C. 5. Сбрасываю модуль I2C в регистрах RCC. 6. Заново инициализирую модуль (включение синхронизации, настройка GPIO и т.д.). Такую последовательность я провожу как при старте ПО, так и в процессе работы девайса при обнаружении заклинивания. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться