pokk 0 2 марта, 2020 Опубликовано 2 марта, 2020 · Жалоба Добрый день, переношу свой проект на FreeRTOS , начал c периферией работающей на I2C. Есть две задачи использующие I2C это термодатчик LM75 и LCD hd44780 (на расширителе PCF). Остановился на обработке ошибок. Алгоритм заложил следующий: Первый тип ошибки это если slave отсутствует на линии ( ожидаем его появления и по появлению вызываем Calback на обработку, для LCD запускаем инициализацию ), соответственно так же пропажу slave с линии Второй тип ошибки если было замыкание линии i2c (переключаем линию CLK на выход и генерируем клоки на сброс slave и запускаем переинициализацию i2c и всех задач) Так вот при отсутствии slave на линии вызывается I2Cx_ER_IRQHandler и по флагу I2C_SR1_AF определяем что нету аск от slave. Как правильно и просто определить какой из двух задач относился вызов I2Cx_ER_IRQHandler т.е какой из 2-3 slave не ответил ? Можно привязаться как нибудь к имени задачи или xTaskNumber? Раньше я сохранял id "задачи" (работал без ртос) а в прерывании смотрел на этот номер, но получалось не очень хорошо (этот модуль тянул ещё дополнительные include ) Как правильно сделать вызов Calback на обработку, событий появления/пропадания slave ? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
haker_fox 55 2 марта, 2020 Опубликовано 2 марта, 2020 · Жалоба 2 minutes ago, pokk said: Как правильно сделать вызов Calback на обработку, событий появления/пропадания slave ? Вот функция для обмена с подчинёнными из моего драйвера TRetVal Lpc43xxI2cDriver::txrx( TMsgType * msg ) { RET_VAL(openResult); TRetVal retVal; configASSERT(m_periphPointer[m_hdwNum]); configASSERT(msg); configASSERT(mutex[m_hdwNum]); if( msg == nullptr ) retVal = rvNULL_POINTER; else { OsApi::Mutex mt(mutex[m_hdwNum]); RET_VAL(mt.take(msg->timeout_ms)); m_tskHandles[m_hdwNum] = xTaskGetCurrentTaskHandle(); I2C_M_SETUP_Type transferMCfg; /* Start I2C slave device first */ transferMCfg.sl_addr7bit = msg->slaveAddr7Bit; transferMCfg.tx_data = msg->tx; transferMCfg.tx_length = msg->txLen; transferMCfg.rx_data = msg->rx; transferMCfg.rx_length = msg->rxLen; transferMCfg.retransmissions_max = 3; I2C_MasterTransferData(m_periphPointer[m_hdwNum], &transferMCfg, I2C_TRANSFER_INTERRUPT); uint32_t notify = ulTaskNotifyTake(pdTRUE, MSEC(msg->timeout_ms)); retVal = notify ? rvOK : rvTIME_OUT; } return retVal; } Обратите внимание, что перед тем, как задача пытается попользоваться шиной, она берёт мьютекс OsApi::Mutex mt(mutex[m_hdwNum]); RET_VAL(mt.take(msg->timeout_ms)); Если в течение таймаута мы захватили мьютекс, то начинаем пользоваться шиной. Соответственно, все транзакции с подчинённым будут только для одной задачи. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
pokk 0 2 марта, 2020 Опубликовано 2 марта, 2020 · Жалоба Понял сохранить id можно через xTaskGetCurrentTaskHandle() буду дальше думать как это можно испольнозовать. 1 hour ago, haker_fox said: transferMCfg.retransmissions_max = 3; А этот параметр как используеться точнее повторение происходит по какому событию ? Если нету slave ? А что дальше делаете после трехкратного повторения ? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Spider 0 7 мая, 2020 Опубликовано 7 мая, 2020 · Жалоба А нельзя в прерывании смотреть кто сейчас держит Mutex и от этого уже отталкиваться? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Andrew_Q 0 8 мая, 2020 Опубликовано 8 мая, 2020 · Жалоба В 07.05.2020 в 09:57, Spider сказал: А нельзя в прерывании смотреть кто сейчас держит Mutex и от этого уже отталкиваться? https://www.freertos.org/xSemaphoreGetMutexHolder.html Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Spider 0 8 мая, 2020 Опубликовано 8 мая, 2020 · Жалоба 1 hour ago, Andrew_Q said: https://www.freertos.org/xSemaphoreGetMutexHolder.html Дык я о том и говорю.... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Andrew_Q 0 21 мая, 2020 Опубликовано 21 мая, 2020 · Жалоба Надо посмотреть чем отличаются fromISR функции от не fromISR и написать оберточку для обращения. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
a_electronic 0 19 февраля, 2021 Опубликовано 19 февраля, 2021 · Жалоба Не нужно так глубоко залазить в железо, если есть HAL и RTOS. Как было правильно замечено, задача перед работой должна захватить мутекс. Потом работа идет по событиям. Пример - фрагмент драйвера KSZ9897: void HAL_I2C_MemTxCpltCallback(I2C_HandleTypeDef *hi2c){ if(hi2c == &hi2c1){ osEventFlagsSet(I2C1EventHandle, 0x01U); return; } } void HAL_I2C_MemRxCpltCallback(I2C_HandleTypeDef *hi2c){ if(hi2c == &hi2c1){ osEventFlagsSet(I2C1EventHandle, 0x01U); return; } } void HAL_I2C_ErrorCallback(I2C_HandleTypeDef *hi2c){ if(hi2c == &hi2c1){ osEventFlagsSet(I2C1EventHandle, 0x02U); return; } } //-------------------------------------------------------------------------- uint16_t EthCtrlWrite8(uint16_t addr, uint8_t src){ uint16_t res; uint32_t ret; abyEthCtrlTmpBuf[0] = src; if((res = HAL_I2C_Mem_Write_IT(&hi2c1, KSZ_I2C_ADDR, addr, KSZ_ADDR_SIZE, abyEthCtrlTmpBuf, 1)) != HAL_OK) { return res; } ret = osEventFlagsWait(I2C1EventHandle, osFlagsWaitAll, osFlagsWaitAny, osWaitForever); // TO DO return HAL_OK; } Понятно, что Event нужно предварительно создать и проинициализировать. Если девайсы на шине могут ВНЕЗАПНО пропадать и появляться, то в ожидании события osWaitForever надо заменить на определенное вменяемое значение и после срабатывания события проанализировать, чего же IRL мы таки дождались: проанализировать возврат ожидания и посмотреть флаги - кто вызвал событие. Ну и ГЛАВНОЕ - не забыть отпустить мутекс))) Тут мутекс не использован, потому что у меня девайсом монопольно рулить один процесс. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться