Перейти к содержанию
    

CAN STM32 Ошибки отправки

Здравствуйте, битый день сижу с одной проблемой. Есть у меня 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 виснет, и отчего эти ошибки отправки могут возникать.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

а какая версия HAL-а?

похоже, что это какая-то старая реализация драйвера (сейчас она уже legacy), которую стмовцы так и не сумели допилить. то что я видел последнее (и уже достаточно давно) было вообще переделано, от похожести на file io они в новом драйвере отказались

у меня была проблема в этом драйвере с LOCK/UNLOCK - то есть где-то он умел оставить флаг залоченности (либо наоборот, какой-то конфликт между прерываниями и программой из-за непоставленного этого флага). вобщем я уже не помню, и не скажу, что досконально разбирался. посмотрите дебагером на структуру hcan поле lock

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

17 hours ago, yes said:

а какая версия HAL-а?

похоже, что это какая-то старая реализация драйвера (сейчас она уже legacy), которую стмовцы так и не сумели допилить. то что я видел последнее (и уже достаточно давно) было вообще переделано, от похожести на file io они в новом драйвере отказались

у меня была проблема в этом драйвере с LOCK/UNLOCK - то есть где-то он умел оставить флаг залоченности (либо наоборот, какой-то конфликт между прерываниями и программой из-за непоставленного этого флага). вобщем я уже не помню, и не скажу, что досконально разбирался. посмотрите дебагером на структуру hcan поле lock

 

У меня поле hcan Lock встает в единицу, когда все виснет, потом вишу в этом самом ожидании таймаута или т.п. Скажите, а как решили проблему того, что HAL лочится, а назад нет?

Чисто вручную отлочить HAL?

версия HAL 1.0.4

У меня отправка идет отлично, а вот прием пакетов чуть пойдет, и виснет, или сразу виснет...

 

Изменено пользователем Ekka

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

если еще не много кода написано, то можно более новый HAL взять, там драйвер проще и прямей (когда в последний раз сталкивался - все заработало сразу), но структуры там другие и логика работы проще, по-моему

я кода не найду - по-моему, убирал я HAL_LOCK в какой-то части, скорее всего в каком-то callback-е из прерывания (по-моему так там сделано). не уверен, что это лучший путь, но тестировалось достаточно долго

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...