/** * @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 This function handles CEC interrupt requests. * @param hcec: CEC handle * @retval None */ void HAL_CEC_IRQHandler(CEC_HandleTypeDef *hcec) { /* Save error status register for further error handling purposes */ hcec->ErrorCode = READ_BIT(hcec->Instance->ESR, CEC_ESR_ALL_ERROR); /* Transmit error */ if(__HAL_CEC_GET_FLAG(hcec, CEC_FLAG_TERR) != RESET) { /* Acknowledgement of the error */ __HAL_CEC_CLEAR_FLAG(hcec, CEC_FLAG_TERR); hcec->gState = HAL_CEC_STATE_READY; } /* Receive error */ if(__HAL_CEC_GET_FLAG(hcec, CEC_FLAG_RERR) != RESET) { /* Acknowledgement of the error */ __HAL_CEC_CLEAR_FLAG(hcec, CEC_FLAG_RERR); hcec->Init.RxBuffer-=hcec->RxXferSize; hcec->RxXferSize = 0U; hcec->RxState = HAL_CEC_STATE_READY; } if((hcec->ErrorCode & CEC_ESR_ALL_ERROR) != 0U) { /* Error Call Back */ HAL_CEC_ErrorCallback(hcec); } /* Transmit byte request or block transfer finished */ if(__HAL_CEC_GET_FLAG(hcec, CEC_FLAG_TBTRF) != RESET) { CEC_Transmit_IT(hcec); } /* Receive byte or block transfer finished */ if(__HAL_CEC_GET_FLAG(hcec, CEC_FLAG_RBTF) != RESET) { if(hcec->RxXferSize == 0U) { /* reception is starting */ hcec->RxState = HAL_CEC_STATE_BUSY_RX; } CEC_Receive_IT(hcec); } }
/** * @brief DeInitializes the CEC peripheral * @param hcec CEC handle * @retval HAL status */ HAL_StatusTypeDef HAL_CEC_DeInit(CEC_HandleTypeDef *hcec) { /* Check the CEC handle allocation */ if(hcec == NULL) { return HAL_ERROR; } /* Check the parameters */ assert_param(IS_CEC_ALL_INSTANCE(hcec->Instance)); hcec->gState = HAL_CEC_STATE_BUSY; /* DeInit the low level hardware */ HAL_CEC_MspDeInit(hcec); /* Disable the Peripheral */ __HAL_CEC_DISABLE(hcec); /* Clear Flags */ __HAL_CEC_CLEAR_FLAG(hcec,CEC_FLAG_TXEND|CEC_FLAG_TXBR|CEC_FLAG_RXBR|CEC_FLAG_RXEND|CEC_ISR_ALL_ERROR); /* Disable the following CEC Transmission/Reception interrupts as * well as the following CEC Transmission/Reception Errors interrupts * Rx Byte Received IT * End of Reception IT * Rx overrun * Rx bit rising error * Rx short bit period error * Rx long bit period error * Rx missing acknowledge * Tx Byte Request IT * End of Transmission IT * Tx Missing Acknowledge IT * Tx-Error IT * Tx-Buffer Underrun IT * Tx arbitration lost */ __HAL_CEC_DISABLE_IT(hcec, CEC_IT_RXBR|CEC_IT_RXEND|CEC_IER_RX_ALL_ERR|CEC_IT_TXBR|CEC_IT_TXEND|CEC_IER_TX_ALL_ERR); hcec->ErrorCode = HAL_CEC_ERROR_NONE; hcec->gState = HAL_CEC_STATE_RESET; hcec->RxState = HAL_CEC_STATE_RESET; /* Process Unlock */ __HAL_UNLOCK(hcec); return HAL_OK; }
/** * @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 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 */ hcec->ErrorCode = hcec->Instance->ISR; /* CEC TX missing acknowledge error interrupt occurred -------------------------------------*/ if((__HAL_CEC_GET_FLAG(hcec, CEC_FLAG_TXACKE) != RESET) && (__HAL_CEC_GET_IT_SOURCE(hcec, CEC_IT_TXACKE) != RESET)) { __HAL_CEC_CLEAR_FLAG(hcec, CEC_FLAG_TXACKE); hcec->State = HAL_CEC_STATE_ERROR; } /* CEC transmit error interrupt occurred --------------------------------------*/ if((__HAL_CEC_GET_FLAG(hcec, CEC_FLAG_TXERR) != RESET) && (__HAL_CEC_GET_IT_SOURCE(hcec, CEC_IT_TXERR) != RESET)) { __HAL_CEC_CLEAR_FLAG(hcec, CEC_FLAG_TXERR); hcec->State = HAL_CEC_STATE_ERROR; } /* CEC TX underrun error interrupt occurred --------------------------------------*/ if((__HAL_CEC_GET_FLAG(hcec, CEC_FLAG_TXUDR) != RESET) && (__HAL_CEC_GET_IT_SOURCE(hcec, CEC_IT_TXUDR) != RESET)) { __HAL_CEC_CLEAR_FLAG(hcec, CEC_FLAG_TXUDR); hcec->State = HAL_CEC_STATE_ERROR; } /* CEC TX arbitration error interrupt occurred --------------------------------------*/ if((__HAL_CEC_GET_FLAG(hcec, CEC_FLAG_ARBLST) != RESET) && (__HAL_CEC_GET_IT_SOURCE(hcec, CEC_IT_ARBLST) != RESET)) { __HAL_CEC_CLEAR_FLAG(hcec, CEC_FLAG_ARBLST); hcec->State = HAL_CEC_STATE_ERROR; } /* CEC RX overrun error interrupt occurred --------------------------------------*/ if((__HAL_CEC_GET_FLAG(hcec, CEC_FLAG_RXOVR) != RESET) && (__HAL_CEC_GET_IT_SOURCE(hcec, CEC_IT_RXOVR) != RESET)) { __HAL_CEC_CLEAR_FLAG(hcec, CEC_FLAG_RXOVR); hcec->State = HAL_CEC_STATE_ERROR; } /* CEC RX bit rising error interrupt occurred --------------------------------------*/ if((__HAL_CEC_GET_FLAG(hcec, CEC_FLAG_BRE) != RESET) && (__HAL_CEC_GET_IT_SOURCE(hcec, CEC_IT_BRE) != RESET)) { __HAL_CEC_CLEAR_FLAG(hcec, CEC_FLAG_BRE); hcec->State = HAL_CEC_STATE_ERROR; } /* CEC RX short bit period error interrupt occurred --------------------------------------*/ if((__HAL_CEC_GET_FLAG(hcec, CEC_FLAG_SBPE) != RESET) && (__HAL_CEC_GET_IT_SOURCE(hcec, CEC_IT_SBPE) != RESET)) { __HAL_CEC_CLEAR_FLAG(hcec, CEC_FLAG_SBPE); hcec->State = HAL_CEC_STATE_ERROR; } /* CEC RX long bit period error interrupt occurred --------------------------------------*/ if((__HAL_CEC_GET_FLAG(hcec, CEC_FLAG_LBPE) != RESET) && (__HAL_CEC_GET_IT_SOURCE(hcec, CEC_IT_LBPE) != RESET)) { __HAL_CEC_CLEAR_FLAG(hcec, CEC_FLAG_LBPE); hcec->State = HAL_CEC_STATE_ERROR; } /* CEC RX missing acknowledge error interrupt occurred --------------------------------------*/ if((__HAL_CEC_GET_FLAG(hcec, CEC_FLAG_RXACKE) != RESET) && (__HAL_CEC_GET_IT_SOURCE(hcec, CEC_IT_RXACKE) != RESET)) { __HAL_CEC_CLEAR_FLAG(hcec, CEC_FLAG_RXACKE); hcec->State = HAL_CEC_STATE_ERROR; } if ((hcec->ErrorCode & CEC_ISR_ALL_ERROR) != 0) { HAL_CEC_ErrorCallback(hcec); } /* CEC RX byte received interrupt ---------------------------------------------------*/ if((__HAL_CEC_GET_FLAG(hcec, CEC_FLAG_RXBR) != RESET) && (__HAL_CEC_GET_IT_SOURCE(hcec, CEC_IT_RXBR) != RESET)) { /* RXBR IT is cleared during HAL_CEC_Transmit_IT processing */ CEC_Receive_IT(hcec); } /* CEC RX end received interrupt ---------------------------------------------------*/ if((__HAL_CEC_GET_FLAG(hcec, CEC_FLAG_RXEND) != RESET) && (__HAL_CEC_GET_IT_SOURCE(hcec, CEC_IT_RXEND) != RESET)) { /* RXBR IT is cleared during HAL_CEC_Transmit_IT processing */ CEC_Receive_IT(hcec); } /* CEC TX byte request interrupt ------------------------------------------------*/ if((__HAL_CEC_GET_FLAG(hcec, CEC_FLAG_TXBR) != RESET) &&(__HAL_CEC_GET_IT_SOURCE(hcec, CEC_IT_TXBR) != RESET)) { /* TXBR IT is cleared during HAL_CEC_Transmit_IT processing */ CEC_Transmit_IT(hcec); } /* CEC TX end interrupt ------------------------------------------------*/ if((__HAL_CEC_GET_FLAG(hcec, CEC_FLAG_TXEND) != RESET) &&(__HAL_CEC_GET_IT_SOURCE(hcec, CEC_IT_TXEND) != RESET)) { /* TXEND IT is cleared during HAL_CEC_Transmit_IT processing */ CEC_Transmit_IT(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 Receive data in blocking mode. Must be invoked when RXBR has been set. * @param hcec: CEC handle * @param pData: pointer to received data buffer. * @param Timeout: Timeout duration. * Note that the received data size is not known beforehand, the latter is known * when the reception is complete and is stored in hcec->RxXferSize. * hcec->RxXferSize is the sum of opcodes + operands (0 to 14 operands max). * If only a header is received, hcec->RxXferSize = 0 * @retval HAL status */ HAL_StatusTypeDef HAL_CEC_Receive(CEC_HandleTypeDef *hcec, uint8_t *pData, uint32_t Timeout) { uint32_t temp; uint32_t tickstart = 0; if (hcec->State == HAL_CEC_STATE_READY) { hcec->ErrorCode = HAL_CEC_ERROR_NONE; if (pData == NULL ) { hcec->State = HAL_CEC_STATE_ERROR; return HAL_ERROR; } hcec->RxXferSize = 0; /* Process Locked */ __HAL_LOCK(hcec); /* Rx loop until CEC_ISR_RXEND is set */ while (HAL_IS_BIT_CLR(hcec->Instance->ISR, CEC_FLAG_RXEND)) { tickstart = HAL_GetTick(); /* Wait for next byte to be received */ while (HAL_IS_BIT_CLR(hcec->Instance->ISR, CEC_FLAG_RXBR)) { if(Timeout != HAL_MAX_DELAY) { if((Timeout == 0) || ((HAL_GetTick() - tickstart) > Timeout)) { hcec->State = HAL_CEC_STATE_TIMEOUT; __HAL_UNLOCK(hcec); return HAL_TIMEOUT; } } /* any error so far ? * has Rx Missing Acknowledge occurred ? * has Rx Long Bit Period error occurred ? * has Rx Short Bit Period error occurred ? * has Rx Bit Rising error occurred ? * has Rx Overrun error occurred ? */ temp = (uint32_t) (hcec->Instance->ISR); if ((temp & (CEC_FLAG_RXACKE|CEC_FLAG_LBPE|CEC_FLAG_SBPE|CEC_FLAG_BRE|CEC_FLAG_RXOVR)) != 0) { /* copy ISR for error handling purposes */ hcec->ErrorCode = temp; /* clear all error flags by default */ __HAL_CEC_CLEAR_FLAG(hcec,(CEC_FLAG_RXACKE|CEC_FLAG_LBPE|CEC_FLAG_SBPE|CEC_FLAG_BRE|CEC_FLAG_RXOVR)); hcec->State = HAL_CEC_STATE_ERROR; __HAL_UNLOCK(hcec); return HAL_ERROR; } } /* while (HAL_IS_BIT_CLR(hcec->Instance->ISR, CEC_ISR_RXBR)) */ /* read received data */ *pData++ = hcec->Instance->RXDR; temp = (uint32_t) (hcec->Instance->ISR); /* end of message ? */ if ((temp & CEC_ISR_RXEND) != 0) { assert_param(IS_CEC_MSGSIZE(hcec->RxXferSize)); __HAL_CEC_CLEAR_FLAG(hcec,CEC_FLAG_RXEND); hcec->State = HAL_CEC_STATE_READY; __HAL_UNLOCK(hcec); return HAL_OK; } /* clear Rx-Byte Received flag */ __HAL_CEC_CLEAR_FLAG(hcec,CEC_FLAG_RXBR); /* increment payload byte counter */ hcec->RxXferSize++; } /* while (HAL_IS_BIT_CLR(hcec->Instance->ISR, CEC_ISR_RXEND)) */ /* if the instructions below are executed, it means RXEND was set when RXBR was * set for the first time: * the code within the "while (HAL_IS_BIT_CLR(hcec->Instance->ISR, CEC_ISR_RXEND))" * loop has not been executed and this means a single byte has been sent */ *pData++ = hcec->Instance->RXDR; /* only one header is received: RxXferSize is set to 0 (no operand, no opcode) */ hcec->RxXferSize = 0; __HAL_CEC_CLEAR_FLAG(hcec, CEC_FLAG_RXEND); hcec->State = HAL_CEC_STATE_READY; __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; } }
/** * @brief Receive data in interrupt mode. * @param hcec: CEC handle. * Function called under interruption only, once * interruptions have been enabled by HAL_CEC_Receive_IT() * @retval HAL status */ static HAL_StatusTypeDef CEC_Receive_IT(CEC_HandleTypeDef *hcec) { uint32_t tempisr; /* Three different conditions are tested to carry out the RX IT processing: * - the IP is in reception stand-by (the IP state is HAL_CEC_STATE_STANDBY_RX) and * the reception of the first byte is starting * - a message reception is already on-going (the IP state is HAL_CEC_STATE_BUSY_RX) * and a new byte is being received * - a transmission has just been started (the IP state is HAL_CEC_STATE_BUSY_TX) * but has been interrupted by a new message reception or discarded due to * arbitration loss: the reception of the first or higher priority message * (the arbitration winner) is starting */ if ((hcec->State == HAL_CEC_STATE_STANDBY_RX) || (hcec->State == HAL_CEC_STATE_BUSY_RX) || (hcec->State == HAL_CEC_STATE_BUSY_TX)) { /* reception is starting */ hcec->State = HAL_CEC_STATE_BUSY_RX; tempisr = (uint32_t) (hcec->Instance->ISR); if ((tempisr & CEC_FLAG_RXBR) != 0) { /* Process Locked */ __HAL_LOCK(hcec); /* read received byte */ *hcec->pRxBuffPtr++ = hcec->Instance->RXDR; /* if last byte has been received */ if ((tempisr & CEC_FLAG_RXEND) != 0) { /* clear IT */ __HAL_CEC_CLEAR_FLAG(hcec, CEC_FLAG_RXBR|CEC_FLAG_RXEND); /* RX interrupts are not disabled at this point. * Indeed, to disable the IT, the IP must be disabled first * which resets the TXSOM flag. In case of arbitration loss, * this leads to a transmission abort. * Therefore, RX interruptions disabling if so required, * is done in HAL_CEC_RxCpltCallback */ /* IP state is moved to READY. * If the IP must remain in standby mode to listen * any new message, it is up to HAL_CEC_RxCpltCallback * to move it again to HAL_CEC_STATE_STANDBY_RX */ hcec->State = HAL_CEC_STATE_READY; /* Call the Process Unlocked before calling the Rx call back API */ __HAL_UNLOCK(hcec); HAL_CEC_RxCpltCallback(hcec); return HAL_OK; } __HAL_CEC_CLEAR_FLAG(hcec, CEC_FLAG_RXBR); hcec->RxXferSize++; /* Process Unlocked */ __HAL_UNLOCK(hcec); return HAL_OK; } else { return HAL_BUSY; } } 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 error status register for further error handling purposes */ hcec->ErrorCode = READ_BIT(hcec->Instance->ESR, CEC_ESR_ALL_ERROR); /* Transmit error */ if((__HAL_CEC_GET_FLAG(hcec, CEC_FLAG_TERR) != RESET)) { /* Acknowledgement of the error */ __HAL_CEC_CLEAR_FLAG(hcec, CEC_FLAG_TERR); /* Check if a receive process is ongoing or not */ if(hcec->State == HAL_CEC_STATE_BUSY_TX_RX) { /* Interrupts are not disabled due to reception still ongoing */ hcec->State = HAL_CEC_STATE_BUSY_RX; } else { /* Disable the CEC Transmission Interrupts */ __HAL_CEC_DISABLE_IT(hcec, CEC_IT_IE); hcec->State = HAL_CEC_STATE_READY; } } /* Receive error */ if((__HAL_CEC_GET_FLAG(hcec, CEC_FLAG_RERR) != RESET)) { /* Acknowledgement of the error */ __HAL_CEC_CLEAR_FLAG(hcec, CEC_FLAG_RERR); /* Check if a transmit process is ongoing or not */ if(hcec->State == HAL_CEC_STATE_BUSY_TX_RX) { /* Interrupts are not disabled due to reception still ongoing */ hcec->State = HAL_CEC_STATE_BUSY_TX; } else { /* Disable the CEC Transmission Interrupts */ __HAL_CEC_DISABLE_IT(hcec, CEC_IT_IE); hcec->State = HAL_CEC_STATE_READY; } } if ((hcec->ErrorCode & CEC_ESR_ALL_ERROR) != 0) { HAL_CEC_ErrorCallback(hcec); } /* Transmit byte request or block transfer finished */ if((__HAL_CEC_GET_FLAG(hcec, CEC_FLAG_TBTRF) != RESET)) { CEC_Transmit_IT(hcec); } /* Receive byte or block transfer finished */ if((__HAL_CEC_GET_FLAG(hcec, CEC_FLAG_RBTF) != RESET)) { CEC_Receive_IT(hcec); } }
/** * @brief Receive data in blocking mode. * @param hcec: CEC handle * @param pData: pointer to received data buffer. * @param Timeout: Timeout duration. * @note The received data size is not known beforehand, the latter is known * when the reception is complete and is stored in hcec->RxXferSize. * hcec->RxXferSize is the sum of opcodes + operands (0 to 14 operands max). * If only a header is received, hcec->RxXferSize = 0 * @retval HAL status */ HAL_StatusTypeDef HAL_CEC_Receive(CEC_HandleTypeDef *hcec, uint8_t *pData, uint32_t Timeout) { uint32_t temp = 0; uint32_t tickstart = 0; if(hcec->State == HAL_CEC_STATE_READY) { if(pData == NULL) { return HAL_ERROR; } /* When a ping is received, RxXferSize is 0*/ /* When a message is received, RxXferSize contains the number of received bytes */ hcec->RxXferSize = CEC_RXXFERSIZE_INITIALIZE; /* Process Locked */ __HAL_LOCK(hcec); hcec->ErrorCode = HAL_CEC_ERROR_NONE; /* Continue the reception until the End Of Message is received (CEC_FLAG_REOM) */ do { /* Timeout handling */ tickstart = HAL_GetTick(); /* Wait for next byte to be received */ while (HAL_IS_BIT_CLR(hcec->Instance->CSR, CEC_FLAG_RBTF)) { /* Timeout handling */ if(Timeout != HAL_MAX_DELAY) { if((Timeout == 0) || ((HAL_GetTick()-tickstart) > Timeout)) { hcec->State = HAL_CEC_STATE_READY; __HAL_UNLOCK(hcec); return HAL_TIMEOUT; } } /* Check if an error occured during the reception */ if(HAL_IS_BIT_SET(hcec->Instance->CSR, CEC_FLAG_RERR)) { /* Copy ESR for error handling purposes */ hcec->ErrorCode = READ_BIT(hcec->Instance->ESR, CEC_ESR_ALL_ERROR); /* Acknowledgement of the error */ __HAL_CEC_CLEAR_FLAG(hcec, CEC_FLAG_RERR); hcec->State = HAL_CEC_STATE_READY; __HAL_UNLOCK(hcec); return HAL_ERROR; } } /* Keep the value of CSR register as the register is cleared during reception process */ temp = hcec->Instance->CSR; /* Read received data */ *pData++ = hcec->Instance->RXD; /* Acknowledge received byte by writing 0x00 */ CLEAR_BIT(hcec->Instance->CSR, CEC_FLAG_RECEIVE_MASK); /* Increment the number of received data */ if(hcec->RxXferSize == CEC_RXXFERSIZE_INITIALIZE) { hcec->RxXferSize = 0; } else { hcec->RxXferSize++; } }while (HAL_IS_BIT_CLR(temp, CEC_FLAG_REOM)); hcec->State = HAL_CEC_STATE_READY; __HAL_UNLOCK(hcec); if(IS_CEC_MSGSIZE(hcec->RxXferSize)) { return HAL_OK; } else { return HAL_ERROR; } } 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 tickstart = 0; /* If the IP is ready */ if((hcec->State == HAL_CEC_STATE_READY) && (__HAL_CEC_GET_TRANSMISSION_START_FLAG(hcec) == RESET)) { /* Basic check on pData pointer */ if(((pData == NULL) && (Size > 0)) || (! IS_CEC_MSGSIZE(Size))) { return HAL_ERROR; } assert_param(IS_CEC_ADDRESS(DestinationAddress)); /* Process Locked */ __HAL_LOCK(hcec); /* Enter the transmit mode */ hcec->State = 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; /* Send header block */ temp = (uint8_t)((uint32_t)(hcec->Init.InitiatorAddress) << CEC_INITIATOR_LSB_POS) | DestinationAddress; hcec->Instance->TXD = temp; /* In case no data to be sent, sender is only pinging the system */ if (Size != 0) { /* Set TX Start of Message (TXSOM) bit */ hcec->Instance->CSR = CEC_FLAG_TSOM; } else { /* Send a ping command */ hcec->Instance->CSR = CEC_FLAG_TEOM|CEC_FLAG_TSOM; } /* Polling TBTRF bit with timeout handling*/ while (hcec->TxXferCount > 0) { /* Decreasing of the number of remaining data to receive */ hcec->TxXferCount--; /* Timeout handling */ tickstart = HAL_GetTick(); /* Waiting for the next data transmission */ while(HAL_IS_BIT_CLR(hcec->Instance->CSR, CEC_FLAG_TBTRF)) { /* Timeout handling */ if(Timeout != HAL_MAX_DELAY) { if((Timeout == 0) || ((HAL_GetTick()-tickstart) > Timeout)) { hcec->State = HAL_CEC_STATE_READY; /* Process Unlocked */ __HAL_UNLOCK(hcec); return HAL_TIMEOUT; } } /* Check if an error occured */ if(HAL_IS_BIT_SET(hcec->Instance->CSR, CEC_FLAG_TERR) || HAL_IS_BIT_SET(hcec->Instance->CSR, CEC_FLAG_RERR)) { /* Copy ESR for error handling purposes */ hcec->ErrorCode = READ_BIT(hcec->Instance->ESR, CEC_ESR_ALL_ERROR); /* Acknowledgement of the error */ __HAL_CEC_CLEAR_FLAG(hcec, CEC_FLAG_TERR); __HAL_CEC_CLEAR_FLAG(hcec, CEC_FLAG_RERR); hcec->State = HAL_CEC_STATE_READY; __HAL_UNLOCK(hcec); return HAL_ERROR; } } /* Write the next data to TX buffer */ hcec->Instance->TXD = *pData++; /* If this is the last byte of the ongoing transmission */ if (hcec->TxXferCount == 0) { /* Acknowledge byte request and signal end of message */ MODIFY_REG(hcec->Instance->CSR, CEC_FLAG_TRANSMIT_MASK, CEC_FLAG_TEOM); } else { /* Acknowledge byte request by writing 0x00 */ MODIFY_REG(hcec->Instance->CSR, CEC_FLAG_TRANSMIT_MASK, 0x00); } } /* Timeout handling */ tickstart = HAL_GetTick(); /* Wait for message transmission completion (TBTRF is set) */ while (HAL_IS_BIT_CLR(hcec->Instance->CSR, CEC_FLAG_TBTRF)) { /* Timeout handling */ if(Timeout != HAL_MAX_DELAY) { if((Timeout == 0) || ((HAL_GetTick()-tickstart) > Timeout)) { hcec->State = HAL_CEC_STATE_READY; __HAL_UNLOCK(hcec); return HAL_TIMEOUT; } } /* Check of error during transmission of the last byte */ if(HAL_IS_BIT_SET(hcec->Instance->CSR, CEC_FLAG_TERR) || HAL_IS_BIT_SET(hcec->Instance->CSR, CEC_FLAG_RERR)) { /* Copy ESR for error handling purposes */ hcec->ErrorCode = READ_BIT(hcec->Instance->ESR, CEC_ESR_ALL_ERROR); /* Acknowledgement of the error */ __HAL_CEC_CLEAR_FLAG(hcec, CEC_FLAG_TERR); __HAL_CEC_CLEAR_FLAG(hcec, CEC_FLAG_RERR); hcec->State = HAL_CEC_STATE_READY; __HAL_UNLOCK(hcec); return HAL_ERROR; } } /* Check of error after the last byte transmission */ if(HAL_IS_BIT_SET(hcec->Instance->CSR, CEC_FLAG_TERR) || HAL_IS_BIT_SET(hcec->Instance->CSR, CEC_FLAG_RERR)) { /* Copy ESR for error handling purposes */ hcec->ErrorCode = READ_BIT(hcec->Instance->ESR, CEC_ESR_ALL_ERROR); /* Acknowledgement of the error */ __HAL_CEC_CLEAR_FLAG(hcec, CEC_FLAG_TERR); __HAL_CEC_CLEAR_FLAG(hcec, CEC_FLAG_RERR); hcec->State = HAL_CEC_STATE_READY; __HAL_UNLOCK(hcec); return HAL_ERROR; } /* Acknowledge successful completion by writing 0x00 */ MODIFY_REG(hcec->Instance->CSR, CEC_FLAG_TRANSMIT_MASK, 0x00); hcec->State = HAL_CEC_STATE_READY; __HAL_UNLOCK(hcec); return HAL_OK; } else { return HAL_BUSY; } }