/** * @brief Send data in interrupt mode * @param hcec: CEC handle. * Function called under interruption only, once * interruptions have been enabled by HAL_CEC_Transmit_IT() * @retval HAL status */ static HAL_StatusTypeDef CEC_Transmit_IT(CEC_HandleTypeDef *hcec) { /* if the IP is already busy or if there is a previous transmission already pending due to arbitration loss */ if ((hcec->State == HAL_CEC_STATE_BUSY_TX) || (__HAL_CEC_GET_TRANSMISSION_START_FLAG(hcec) != RESET)) { /* set state to BUSY TX, in case it wasn't set already (case * of transmission new attempt after arbitration loss) */ if (hcec->State != HAL_CEC_STATE_BUSY_TX) { hcec->State = HAL_CEC_STATE_BUSY_TX; } /* if all data have been sent */ if(hcec->TxXferCount == 0) { /* Disable Peripheral to write CEC_IER register */ __HAL_CEC_DISABLE(hcec); /* Disable the CEC Transmission Interrupts */ __HAL_CEC_DISABLE_IT(hcec, CEC_IER_TXBRIE|CEC_IER_TXENDIE); /* Disable the CEC Transmission Error Interrupts */ __HAL_CEC_DISABLE_IT(hcec, CEC_IER_TX_ALL_ERR); /* Enable the Peripheral */ __HAL_CEC_ENABLE(hcec); __HAL_CEC_CLEAR_FLAG(hcec,CEC_ISR_TXBR|CEC_ISR_TXEND); hcec->State = HAL_CEC_STATE_READY; HAL_CEC_TxCpltCallback(hcec); return HAL_OK; } else { if (hcec->TxXferCount == 1) { /* if this is the last byte transmission, set TX End of Message (TXEOM) bit */ __HAL_CEC_LAST_BYTE_TX_SET(hcec); } /* clear Tx-Byte request flag */ __HAL_CEC_CLEAR_FLAG(hcec,CEC_ISR_TXBR); hcec->Instance->TXDR = *hcec->pTxBuffPtr++; hcec->TxXferCount--; return HAL_OK; } } else { return HAL_BUSY; } }
/** * @brief Send data in interrupt mode * @param hcec: CEC handle * @param InitiatorAddress: Initiator address * @param DestinationAddress: destination logical address * @param pData: pointer to input byte data buffer * @param Size: amount of data to be sent in bytes (without counting the header). * 0 means only the header is sent (ping operation). * Maximum TX size is 15 bytes (1 opcode and up to 14 operands). * @retval HAL status */ HAL_StatusTypeDef HAL_CEC_Transmit_IT(CEC_HandleTypeDef *hcec, uint8_t InitiatorAddress, uint8_t DestinationAddress, uint8_t *pData, uint32_t Size) { /* if the IP isn't already busy and if there is no previous transmission already pending due to arbitration lost */ if (hcec->gState == HAL_CEC_STATE_READY) { if((pData == NULL ) && (Size > 0U)) { return HAL_ERROR; } assert_param(IS_CEC_ADDRESS(DestinationAddress)); assert_param(IS_CEC_ADDRESS(InitiatorAddress)); assert_param(IS_CEC_MSGSIZE(Size)); /* Process Locked */ __HAL_LOCK(hcec); hcec->pTxBuffPtr = pData; hcec->gState = HAL_CEC_STATE_BUSY_TX; hcec->ErrorCode = HAL_CEC_ERROR_NONE; /* initialize the number of bytes to send, * 0 means only one header is sent (ping operation) */ hcec->TxXferCount = Size; /* in case of no payload (Size = 0), sender is only pinging the system; Set TX End of Message (TXEOM) bit, must be set before writing data to TXDR */ if (Size == 0U) { __HAL_CEC_LAST_BYTE_TX_SET(hcec); } /* send header block */ hcec->Instance->TXDR = ((uint8_t)(InitiatorAddress << CEC_INITIATOR_LSB_POS) |(uint8_t) DestinationAddress); /* Set TX Start of Message (TXSOM) bit */ __HAL_CEC_FIRST_BYTE_TX_SET(hcec); /* Process Unlocked */ __HAL_UNLOCK(hcec); return HAL_OK; } else { return HAL_BUSY; } }
/** * @brief This function handles CEC interrupt requests. * @param hcec: CEC handle * @retval None */ void HAL_CEC_IRQHandler(CEC_HandleTypeDef *hcec) { /* save interrupts register for further error or interrupts handling purposes */ uint32_t reg = 0U; reg = hcec->Instance->ISR; /* ----------------------------Arbitration Lost Management----------------------------------*/ /* CEC TX arbitration error interrupt occurred --------------------------------------*/ if((reg & CEC_FLAG_ARBLST) != RESET) { hcec->ErrorCode = HAL_CEC_ERROR_ARBLST; __HAL_CEC_CLEAR_FLAG(hcec, CEC_FLAG_ARBLST); } /* ----------------------------Rx Management----------------------------------*/ /* CEC RX byte received interrupt ---------------------------------------------------*/ if((reg & CEC_FLAG_RXBR) != RESET) { /* reception is starting */ hcec->RxState = HAL_CEC_STATE_BUSY_RX; hcec->RxXferSize++; /* read received byte */ *hcec->Init.RxBuffer++ = hcec->Instance->RXDR; __HAL_CEC_CLEAR_FLAG(hcec, CEC_FLAG_RXBR); } /* CEC RX end received interrupt ---------------------------------------------------*/ if((reg & CEC_FLAG_RXEND) != RESET) { /* clear IT */ __HAL_CEC_CLEAR_FLAG(hcec, CEC_FLAG_RXEND); /* Rx process is completed, restore hcec->RxState to Ready */ hcec->RxState = HAL_CEC_STATE_READY; hcec->ErrorCode = HAL_CEC_ERROR_NONE; hcec->Init.RxBuffer -= hcec->RxXferSize; HAL_CEC_RxCpltCallback(hcec, hcec->RxXferSize); hcec->RxXferSize = 0U; } /* ----------------------------Tx Management----------------------------------*/ /* CEC TX byte request interrupt ------------------------------------------------*/ if((reg & CEC_FLAG_TXBR) != RESET) { if (hcec->TxXferCount == 0U) { /* if this is the last byte transmission, set TX End of Message (TXEOM) bit */ __HAL_CEC_LAST_BYTE_TX_SET(hcec); hcec->Instance->TXDR = *hcec->pTxBuffPtr++; } else { hcec->Instance->TXDR = *hcec->pTxBuffPtr++; hcec->TxXferCount--; } /* clear Tx-Byte request flag */ __HAL_CEC_CLEAR_FLAG(hcec,CEC_FLAG_TXBR); } /* CEC TX end interrupt ------------------------------------------------*/ if((reg & CEC_FLAG_TXEND) != RESET) { __HAL_CEC_CLEAR_FLAG(hcec, CEC_FLAG_TXEND); /* Tx process is ended, restore hcec->gState to Ready */ hcec->gState = HAL_CEC_STATE_READY; /* Call the Process Unlocked before calling the Tx call back API to give the possibility to start again the Transmission under the Tx call back API */ __HAL_UNLOCK(hcec); hcec->ErrorCode = HAL_CEC_ERROR_NONE; HAL_CEC_TxCpltCallback(hcec); } /* ----------------------------Rx/Tx Error Management----------------------------------*/ if ((reg & (CEC_ISR_RXOVR|CEC_ISR_BRE|CEC_ISR_SBPE|CEC_ISR_LBPE|CEC_ISR_RXACKE|CEC_ISR_TXUDR|CEC_ISR_TXERR|CEC_ISR_TXACKE)) != 0U) { hcec->ErrorCode = reg; __HAL_CEC_CLEAR_FLAG(hcec, HAL_CEC_ERROR_RXOVR|HAL_CEC_ERROR_BRE|CEC_FLAG_LBPE|CEC_FLAG_SBPE|HAL_CEC_ERROR_RXACKE|HAL_CEC_ERROR_TXUDR|HAL_CEC_ERROR_TXERR|HAL_CEC_ERROR_TXACKE); if((reg & (CEC_ISR_RXOVR|CEC_ISR_BRE|CEC_ISR_SBPE|CEC_ISR_LBPE|CEC_ISR_RXACKE)) != RESET) { hcec->Init.RxBuffer-=hcec->RxXferSize; hcec->RxXferSize = 0U; hcec->RxState = HAL_CEC_STATE_READY; } else if (((reg & (CEC_ISR_TXUDR|CEC_ISR_TXERR|CEC_ISR_TXACKE)) != RESET) && ((reg & CEC_ISR_ARBLST) == RESET)) { /* Set the CEC state ready to be able to start again the process */ hcec->gState = HAL_CEC_STATE_READY; } /* Error Call Back */ HAL_CEC_ErrorCallback(hcec); } }
/** * @brief Send data in interrupt mode * @param hcec: CEC handle * @param DestinationAddress: destination logical address * @param pData: pointer to input byte data buffer * @param Size: amount of data to be sent in bytes (without counting the header). * 0 means only the header is sent (ping operation). * Maximum TX size is 15 bytes (1 opcode and up to 14 operands). * @retval HAL status */ HAL_StatusTypeDef HAL_CEC_Transmit_IT(CEC_HandleTypeDef *hcec, uint8_t DestinationAddress, uint8_t *pData, uint32_t Size) { uint8_t temp = 0; /* if the IP isn't already busy and if there is no previous transmission already pending due to arbitration lost */ if (((hcec->State == HAL_CEC_STATE_READY) || (hcec->State == HAL_CEC_STATE_STANDBY_RX)) && (__HAL_CEC_GET_TRANSMISSION_START_FLAG(hcec) == RESET)) { if((pData == NULL ) && (Size > 0)) { hcec->State = HAL_CEC_STATE_ERROR; return HAL_ERROR; } assert_param(IS_CEC_ADDRESS(DestinationAddress)); assert_param(IS_CEC_MSGSIZE(Size)); /* Process Locked */ __HAL_LOCK(hcec); hcec->pTxBuffPtr = pData; hcec->State = HAL_CEC_STATE_BUSY_TX; hcec->ErrorCode = HAL_CEC_ERROR_NONE; /* Disable Peripheral to write CEC_IER register */ __HAL_CEC_DISABLE(hcec); /* Enable the following two CEC Transmission interrupts as * well as the following CEC Transmission Errors interrupts: * Tx Byte Request IT * End of Transmission IT * Tx Missing Acknowledge IT * Tx-Error IT * Tx-Buffer Underrun IT * Tx arbitration lost */ __HAL_CEC_ENABLE_IT(hcec, CEC_IT_TXBR|CEC_IT_TXEND|CEC_IER_TX_ALL_ERR); /* Enable the Peripheral */ __HAL_CEC_ENABLE(hcec); /* initialize the number of bytes to send, * 0 means only one header is sent (ping operation) */ hcec->TxXferCount = Size; /* Process Unlocked */ __HAL_UNLOCK(hcec); /* in case of no payload (Size = 0), sender is only pinging the system; * Set TX End of Message (TXEOM) bit, must be set before writing data to TXDR */ if (Size == 0) { __HAL_CEC_LAST_BYTE_TX_SET(hcec); } /* send header block */ temp = ((uint32_t)hcec->Init.InitiatorAddress << CEC_INITIATOR_LSB_POS) | DestinationAddress; hcec->Instance->TXDR = temp; /* Set TX Start of Message (TXSOM) bit */ __HAL_CEC_FIRST_BYTE_TX_SET(hcec); return HAL_OK; } /* if the IP is already busy or if there is a previous transmission already pending due to arbitration loss */ else if ((hcec->State == HAL_CEC_STATE_BUSY_TX) || (__HAL_CEC_GET_TRANSMISSION_START_FLAG(hcec) != RESET)) { __HAL_LOCK(hcec); /* set state to BUSY TX, in case it wasn't set already (case * of transmission new attempt after arbitration loss) */ if (hcec->State != HAL_CEC_STATE_BUSY_TX) { hcec->State = HAL_CEC_STATE_BUSY_TX; } /* if all data have been sent */ if(hcec->TxXferCount == 0) { /* Disable Peripheral to write CEC_IER register */ __HAL_CEC_DISABLE(hcec); /* Disable the CEC Transmission Interrupts */ __HAL_CEC_DISABLE_IT(hcec, CEC_IT_TXBR|CEC_IT_TXEND); /* Disable the CEC Transmission Error Interrupts */ __HAL_CEC_DISABLE_IT(hcec, CEC_IER_TX_ALL_ERR); /* Enable the Peripheral */ __HAL_CEC_ENABLE(hcec); __HAL_CEC_CLEAR_FLAG(hcec, CEC_FLAG_TXBR|CEC_FLAG_TXEND); hcec->State = HAL_CEC_STATE_READY; /* Call the Process Unlocked before calling the Tx call back API to give the possibility to start again the Transmission under the Tx call back API */ __HAL_UNLOCK(hcec); HAL_CEC_TxCpltCallback(hcec); return HAL_OK; } else { if (hcec->TxXferCount == 1) { /* if this is the last byte transmission, set TX End of Message (TXEOM) bit */ __HAL_CEC_LAST_BYTE_TX_SET(hcec); } /* clear Tx-Byte request flag */ __HAL_CEC_CLEAR_FLAG(hcec, CEC_FLAG_TXBR); hcec->Instance->TXDR = *hcec->pTxBuffPtr++; hcec->TxXferCount--; /* Process Unlocked */ __HAL_UNLOCK(hcec); return HAL_OK; } } else { return HAL_BUSY; } }
/** * @brief Send data in blocking mode * @param hcec: CEC handle * @param DestinationAddress: destination logical address * @param pData: pointer to input byte data buffer * @param Size: amount of data to be sent in bytes (without counting the header). * 0 means only the header is sent (ping operation). * Maximum TX size is 15 bytes (1 opcode and up to 14 operands). * @param Timeout: Timeout duration. * @retval HAL status */ HAL_StatusTypeDef HAL_CEC_Transmit(CEC_HandleTypeDef *hcec, uint8_t DestinationAddress, uint8_t *pData, uint32_t Size, uint32_t Timeout) { uint8_t temp = 0; uint32_t tempisr = 0; uint32_t tickstart = 0; if((hcec->State == HAL_CEC_STATE_READY) && (__HAL_CEC_GET_TRANSMISSION_START_FLAG(hcec) == RESET)) { hcec->ErrorCode = HAL_CEC_ERROR_NONE; if((pData == NULL ) && (Size > 0)) { hcec->State = HAL_CEC_STATE_ERROR; return HAL_ERROR; } assert_param(IS_CEC_ADDRESS(DestinationAddress)); assert_param(IS_CEC_MSGSIZE(Size)); /* Process Locked */ __HAL_LOCK(hcec); hcec->State = HAL_CEC_STATE_BUSY_TX; hcec->TxXferCount = Size; /* case no data to be sent, sender is only pinging the system */ if (Size == 0) { /* Set TX End of Message (TXEOM) bit, must be set before writing data to TXDR */ __HAL_CEC_LAST_BYTE_TX_SET(hcec); } /* send header block */ temp = ((uint32_t)hcec->Init.InitiatorAddress << CEC_INITIATOR_LSB_POS) | DestinationAddress; hcec->Instance->TXDR = temp; /* Set TX Start of Message (TXSOM) bit */ __HAL_CEC_FIRST_BYTE_TX_SET(hcec); while (hcec->TxXferCount > 0) { hcec->TxXferCount--; tickstart = HAL_GetTick(); while(HAL_IS_BIT_CLR(hcec->Instance->ISR, CEC_FLAG_TXBR)) { if(Timeout != HAL_MAX_DELAY) { if((Timeout == 0) || ((HAL_GetTick() - tickstart) > Timeout)) { hcec->State = HAL_CEC_STATE_TIMEOUT; /* Process Unlocked */ __HAL_UNLOCK(hcec); return HAL_TIMEOUT; } } /* check whether error occurred while waiting for TXBR to be set: * has Tx underrun occurred ? * has Tx error occurred ? * has Tx Missing Acknowledge error occurred ? * has Arbitration Loss error occurred ? */ tempisr = hcec->Instance->ISR; if ((tempisr & (CEC_FLAG_TXUDR|CEC_FLAG_TXERR|CEC_FLAG_TXACKE|CEC_FLAG_ARBLST)) != 0) { /* copy ISR for error handling purposes */ hcec->ErrorCode = tempisr; /* clear all error flags by default */ __HAL_CEC_CLEAR_FLAG(hcec, (CEC_FLAG_TXUDR|CEC_FLAG_TXERR|CEC_FLAG_TXACKE|CEC_FLAG_ARBLST)); hcec->State = HAL_CEC_STATE_ERROR; __HAL_UNLOCK(hcec); return HAL_ERROR; } } /* TXBR to clear BEFORE writing TXDR register */ __HAL_CEC_CLEAR_FLAG(hcec, CEC_FLAG_TXBR); if (hcec->TxXferCount == 0) { /* if last byte transmission, set TX End of Message (TXEOM) bit */ __HAL_CEC_LAST_BYTE_TX_SET(hcec); } hcec->Instance->TXDR = *pData++; /* error check after TX byte write up */ tempisr = hcec->Instance->ISR; if ((tempisr & (CEC_FLAG_TXUDR|CEC_FLAG_TXERR|CEC_FLAG_TXACKE|CEC_FLAG_ARBLST)) != 0) { /* copy ISR for error handling purposes */ hcec->ErrorCode = tempisr; /* clear all error flags by default */ __HAL_CEC_CLEAR_FLAG(hcec, (CEC_FLAG_TXUDR|CEC_FLAG_TXERR|CEC_FLAG_TXACKE|CEC_FLAG_ARBLST)); hcec->State = HAL_CEC_STATE_ERROR; __HAL_UNLOCK(hcec); return HAL_ERROR; } } /* end while (while (hcec->TxXferCount > 0)) */ /* if no error up to this point, check that transmission is * complete, that is wait until TXEOM is reset */ tickstart = HAL_GetTick(); while (HAL_IS_BIT_SET(hcec->Instance->CR, CEC_CR_TXEOM)) { if(Timeout != HAL_MAX_DELAY) { if((Timeout == 0) || ((HAL_GetTick() - tickstart) > Timeout)) { hcec->State = HAL_CEC_STATE_ERROR; __HAL_UNLOCK(hcec); return HAL_TIMEOUT; } } } /* Final error check once all bytes have been transmitted */ tempisr = hcec->Instance->ISR; if ((tempisr & (CEC_FLAG_TXUDR|CEC_FLAG_TXERR|CEC_FLAG_TXACKE)) != 0) { /* copy ISR for error handling purposes */ hcec->ErrorCode = tempisr; /* clear all error flags by default */ __HAL_CEC_CLEAR_FLAG(hcec, (CEC_FLAG_TXUDR|CEC_FLAG_TXERR|CEC_FLAG_TXACKE)); hcec->State = HAL_CEC_STATE_ERROR; __HAL_UNLOCK(hcec); return HAL_ERROR; } hcec->State = HAL_CEC_STATE_READY; __HAL_UNLOCK(hcec); return HAL_OK; } else { return HAL_BUSY; } }