Ekka 0 4 сентября, 2019 Опубликовано 4 сентября, 2019 · Жалоба Здравствуйте, битый день сижу с одной проблемой. Есть у меня CAN, заинициализированный от HAL (знаю, HAL - та еще ...рень, но требования). Через какое-то время происходят куча ошибок отправки и CAN виснет от переполнения ошибок отправки. Точнее он уходит в ожидание, переменная системного таймера uwTick, используемая в CAN_TRANSMIT перестает меняться и все виснет. вишу в этой функции HAL_StatusTypeDef HAL_CAN_Transmit(CAN_HandleTypeDef* hcan, uint32_t Timeout) { uint32_t transmitmailbox = CAN_TXSTATUS_NOMAILBOX; uint32_t tickstart = 0; /* Check the parameters */ assert_param(IS_CAN_IDTYPE(hcan->pTxMsg->IDE)); assert_param(IS_CAN_RTR(hcan->pTxMsg->RTR)); assert_param(IS_CAN_DLC(hcan->pTxMsg->DLC)); /* Process locked */ __HAL_LOCK(hcan); if(hcan->State == HAL_CAN_STATE_BUSY_RX) { /* Change CAN state */ hcan->State = HAL_CAN_STATE_BUSY_TX_RX; } else { /* Change CAN state */ hcan->State = HAL_CAN_STATE_BUSY_TX; } /* Select one empty transmit mailbox */ if (HAL_IS_BIT_SET(hcan->Instance->TSR, CAN_TSR_TME0)) { transmitmailbox = 0; } else if (HAL_IS_BIT_SET(hcan->Instance->TSR, CAN_TSR_TME1)) { transmitmailbox = 1; } else if (HAL_IS_BIT_SET(hcan->Instance->TSR, CAN_TSR_TME2)) { transmitmailbox = 2; } else { transmitmailbox = CAN_TXSTATUS_NOMAILBOX; } if (transmitmailbox != CAN_TXSTATUS_NOMAILBOX) { /* Set up the Id */ hcan->Instance->sTxMailBox[transmitmailbox].TIR &= CAN_TI0R_TXRQ; if (hcan->pTxMsg->IDE == CAN_ID_STD) { assert_param(IS_CAN_STDID(hcan->pTxMsg->StdId)); hcan->Instance->sTxMailBox[transmitmailbox].TIR |= ((hcan->pTxMsg->StdId << CAN_TI0R_STID_BIT_POSITION) | hcan->pTxMsg->RTR); } else { assert_param(IS_CAN_EXTID(hcan->pTxMsg->ExtId)); hcan->Instance->sTxMailBox[transmitmailbox].TIR |= ((hcan->pTxMsg->ExtId << CAN_TI0R_EXID_BIT_POSITION) | hcan->pTxMsg->IDE | hcan->pTxMsg->RTR); } /* Set up the DLC */ hcan->pTxMsg->DLC &= (uint8_t)0x0000000F; hcan->Instance->sTxMailBox[transmitmailbox].TDTR &= (uint32_t)0xFFFFFFF0; hcan->Instance->sTxMailBox[transmitmailbox].TDTR |= hcan->pTxMsg->DLC; /* Set up the data field */ WRITE_REG(hcan->Instance->sTxMailBox[transmitmailbox].TDLR, ((uint32_t)hcan->pTxMsg->Data[3] << CAN_TDL0R_DATA3_BIT_POSITION) | ((uint32_t)hcan->pTxMsg->Data[2] << CAN_TDL0R_DATA2_BIT_POSITION) | ((uint32_t)hcan->pTxMsg->Data[1] << CAN_TDL0R_DATA1_BIT_POSITION) | ((uint32_t)hcan->pTxMsg->Data[0] << CAN_TDL0R_DATA0_BIT_POSITION) ); WRITE_REG(hcan->Instance->sTxMailBox[transmitmailbox].TDHR, ((uint32_t)hcan->pTxMsg->Data[7] << CAN_TDL0R_DATA3_BIT_POSITION) | ((uint32_t)hcan->pTxMsg->Data[6] << CAN_TDL0R_DATA2_BIT_POSITION) | ((uint32_t)hcan->pTxMsg->Data[5] << CAN_TDL0R_DATA1_BIT_POSITION) | ((uint32_t)hcan->pTxMsg->Data[4] << CAN_TDL0R_DATA0_BIT_POSITION) ); /* Request transmission */ SET_BIT(hcan->Instance->sTxMailBox[transmitmailbox].TIR, CAN_TI0R_TXRQ); /* Get timeout */ tickstart = HAL_GetTick(); /* Check End of transmission flag */ while(!(__HAL_CAN_TRANSMIT_STATUS(hcan, transmitmailbox))) { /* Check for the Timeout */ if(Timeout != HAL_MAX_DELAY) { if((Timeout == 0) || ((HAL_GetTick()-tickstart) > Timeout)) { hcan->State = HAL_CAN_STATE_TIMEOUT; /* Process unlocked */ __HAL_UNLOCK(hcan); return HAL_TIMEOUT; } } } if(hcan->State == HAL_CAN_STATE_BUSY_TX_RX) { /* Change CAN state */ hcan->State = HAL_CAN_STATE_BUSY_RX; /* Process unlocked */ __HAL_UNLOCK(hcan); } else { /* Change CAN state */ hcan->State = HAL_CAN_STATE_READY; } /* Process unlocked */ __HAL_UNLOCK(hcan); /* Return function status */ return HAL_OK; } else { /* Change CAN state */ hcan->State = HAL_CAN_STATE_ERROR; /* Process unlocked */ __HAL_UNLOCK(hcan); /* Return function status */ return HAL_ERROR; } } в строке .... /* Get timeout */ tickstart = HAL_GetTick(); /* Check End of transmission flag */ while(!(__HAL_CAN_TRANSMIT_STATUS(hcan, transmitmailbox))) { /* Check for the Timeout */ if(Timeout != HAL_MAX_DELAY) { if((Timeout == 0) || ((HAL_GetTick()-tickstart) > Timeout)) { ...} может, кто-нибудь знает, почему N-го количества отправок CAN виснет, и отчего эти ошибки отправки могут возникать. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
yes 5 4 сентября, 2019 Опубликовано 4 сентября, 2019 · Жалоба а какая версия HAL-а? похоже, что это какая-то старая реализация драйвера (сейчас она уже legacy), которую стмовцы так и не сумели допилить. то что я видел последнее (и уже достаточно давно) было вообще переделано, от похожести на file io они в новом драйвере отказались у меня была проблема в этом драйвере с LOCK/UNLOCK - то есть где-то он умел оставить флаг залоченности (либо наоборот, какой-то конфликт между прерываниями и программой из-за непоставленного этого флага). вобщем я уже не помню, и не скажу, что досконально разбирался. посмотрите дебагером на структуру hcan поле lock Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Ekka 0 5 сентября, 2019 Опубликовано 5 сентября, 2019 (изменено) · Жалоба 17 hours ago, yes said: а какая версия HAL-а? похоже, что это какая-то старая реализация драйвера (сейчас она уже legacy), которую стмовцы так и не сумели допилить. то что я видел последнее (и уже достаточно давно) было вообще переделано, от похожести на file io они в новом драйвере отказались у меня была проблема в этом драйвере с LOCK/UNLOCK - то есть где-то он умел оставить флаг залоченности (либо наоборот, какой-то конфликт между прерываниями и программой из-за непоставленного этого флага). вобщем я уже не помню, и не скажу, что досконально разбирался. посмотрите дебагером на структуру hcan поле lock У меня поле hcan Lock встает в единицу, когда все виснет, потом вишу в этом самом ожидании таймаута или т.п. Скажите, а как решили проблему того, что HAL лочится, а назад нет? Чисто вручную отлочить HAL? версия HAL 1.0.4 У меня отправка идет отлично, а вот прием пакетов чуть пойдет, и виснет, или сразу виснет... Изменено 5 сентября, 2019 пользователем Ekka Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
yes 5 5 сентября, 2019 Опубликовано 5 сентября, 2019 · Жалоба если еще не много кода написано, то можно более новый HAL взять, там драйвер проще и прямей (когда в последний раз сталкивался - все заработало сразу), но структуры там другие и логика работы проще, по-моему я кода не найду - по-моему, убирал я HAL_LOCK в какой-то части, скорее всего в каком-то callback-е из прерывания (по-моему так там сделано). не уверен, что это лучший путь, но тестировалось достаточно долго Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться