1 /**
2   ******************************************************************************
3   * @file    stm32mp1xx_hal_cec.c
4   * @author  MCD Application Team
5   * @brief   CEC HAL module driver.
6   *          This file provides firmware functions to manage the following
7   *          functionalities of the High Definition Multimedia Interface
8   *          Consumer Electronics Control Peripheral (CEC).
9   *           + Initialization and de-initialization function
10   *           + IO operation function
11   *           + Peripheral Control function
12   *
13   *
14   ******************************************************************************
15   * @attention
16   *
17   * Copyright (c) 2019 STMicroelectronics.
18   * All rights reserved.
19   *
20   * This software is licensed under terms that can be found in the LICENSE file
21   * in the root directory of this software component.
22   * If no LICENSE file comes with this software, it is provided AS-IS.
23   *
24   ******************************************************************************
25   @verbatim
26  ===============================================================================
27                         ##### How to use this driver #####
28  ===============================================================================
29     [..]
30     The CEC HAL driver can be used as follow:
31 
32     (#) Declare a CEC_HandleTypeDef handle structure.
33     (#) Initialize the CEC low level resources by implementing the HAL_CEC_MspInit ()API:
34         (##) Enable the CEC interface clock.
35         (##) CEC pins configuration:
36             (+++) Enable the clock for the CEC GPIOs.
37             (+++) Configure these CEC pins as alternate function pull-up.
38         (##) NVIC configuration if you need to use interrupt process (HAL_CEC_Transmit_IT()
39              and HAL_CEC_Receive_IT() APIs):
40             (+++) Configure the CEC interrupt priority.
41             (+++) Enable the NVIC CEC IRQ handle.
42             (+++) The specific CEC interrupts (Transmission complete interrupt,
43                   RXNE interrupt and Error Interrupts) will be managed using the macros
44                   __HAL_CEC_ENABLE_IT() and __HAL_CEC_DISABLE_IT() inside the transmit
45                   and receive process.
46 
47     (#) Program the Signal Free Time (SFT) and SFT option, Tolerance, reception stop in
48         in case of Bit Rising Error, Error-Bit generation conditions, device logical
49         address and Listen mode in the hcec Init structure.
50 
51     (#) Initialize the CEC registers by calling the HAL_CEC_Init() API.
52 
53   [..]
54     (@) This API (HAL_CEC_Init()) configures also the low level Hardware (GPIO, CLOCK, CORTEX...etc)
55         by calling the customed HAL_CEC_MspInit() API.
56   *** Callback registration ***
57   =============================================
58 
59   The compilation define  USE_HAL_CEC_REGISTER_CALLBACKS when set to 1
60   allows the user to configure dynamically the driver callbacks.
61   Use Functions @ref HAL_CEC_RegisterCallback() or HAL_CEC_RegisterXXXCallback()
62   to register an interrupt callback.
63 
64   Function @ref HAL_CEC_RegisterCallback() allows to register following callbacks:
65     (+) TxCpltCallback     : Tx Transfer completed callback.
66     (+) ErrorCallback      : callback for error detection.
67     (+) MspInitCallback    : CEC MspInit.
68     (+) MspDeInitCallback  : CEC MspDeInit.
69   This function takes as parameters the HAL peripheral handle, the Callback ID
70   and a pointer to the user callback function.
71 
72   For specific callback HAL_CEC_RxCpltCallback use dedicated register callbacks
73   @ref HAL_CEC_RegisterRxCpltCallback().
74 
75   Use function @ref HAL_CEC_UnRegisterCallback() to reset a callback to the default
76   weak function.
77   @ref HAL_CEC_UnRegisterCallback() takes as parameters the HAL peripheral handle,
78   and the Callback ID.
79   This function allows to reset following callbacks:
80     (+) TxCpltCallback     : Tx Transfer completed callback.
81     (+) ErrorCallback      : callback for error detection.
82     (+) MspInitCallback    : CEC MspInit.
83     (+) MspDeInitCallback  : CEC MspDeInit.
84 
85   For callback HAL_CEC_RxCpltCallback use dedicated unregister callback :
86   @ref HAL_CEC_UnRegisterRxCpltCallback().
87 
88   By default, after the @ref HAL_CEC_Init() and when the state is HAL_CEC_STATE_RESET
89   all callbacks are set to the corresponding weak functions :
90   examples @ref HAL_CEC_TxCpltCallback() , @ref HAL_CEC_RxCpltCallback().
91   Exception done for MspInit and MspDeInit functions that are
92   reset to the legacy weak function in the @ref HAL_CEC_Init()/ @ref HAL_CEC_DeInit() only when
93   these callbacks are null (not registered beforehand).
94   if not, MspInit or MspDeInit are not null, the @ref HAL_CEC_Init() / @ref HAL_CEC_DeInit()
95   keep and use the user MspInit/MspDeInit functions (registered beforehand)
96 
97   Callbacks can be registered/unregistered in HAL_CEC_STATE_READY state only.
98   Exception done MspInit/MspDeInit callbacks that can be registered/unregistered
99   in HAL_CEC_STATE_READY or HAL_CEC_STATE_RESET state,
100   thus registered (user) MspInit/DeInit callbacks can be used during the Init/DeInit.
101   In that case first register the MspInit/MspDeInit user callbacks
102   using @ref HAL_CEC_RegisterCallback() before calling @ref HAL_CEC_DeInit()
103   or @ref HAL_CEC_Init() function.
104 
105   When the compilation define USE_HAL_CEC_REGISTER_CALLBACKS is set to 0 or
106   not defined, the callback registration feature is not available and all callbacks
107   are set to the corresponding weak functions.
108   @endverbatim
109   ******************************************************************************
110   */
111 
112 /* Includes ------------------------------------------------------------------*/
113 #include "stm32mp1xx_hal.h"
114 
115 /** @addtogroup STM32MP1xx_HAL_Driver
116   * @{
117   */
118 
119 /** @defgroup CEC CEC
120   * @brief HAL CEC module driver
121   * @{
122   */
123 #ifdef HAL_CEC_MODULE_ENABLED
124 #if defined (CEC)
125 
126 /* Private typedef -----------------------------------------------------------*/
127 /* Private define ------------------------------------------------------------*/
128 /** @defgroup CEC_Private_Constants CEC Private Constants
129   * @{
130   */
131 /**
132   * @}
133   */
134 
135 /* Private macro -------------------------------------------------------------*/
136 /* Private variables ---------------------------------------------------------*/
137 /* Private function prototypes -----------------------------------------------*/
138 /** @defgroup CEC_Private_Functions CEC Private Functions
139   * @{
140   */
141 /**
142   * @}
143   */
144 
145 /* Exported functions ---------------------------------------------------------*/
146 
147 /** @defgroup CEC_Exported_Functions CEC Exported Functions
148   * @{
149   */
150 
151 /** @defgroup CEC_Exported_Functions_Group1 Initialization and de-initialization functions
152   *  @brief    Initialization and Configuration functions
153   *
154 @verbatim
155 ===============================================================================
156             ##### Initialization and Configuration functions #####
157  ===============================================================================
158     [..]
159     This subsection provides a set of functions allowing to initialize the CEC
160       (+) The following parameters need to be configured:
161         (++) SignalFreeTime
162         (++) Tolerance
163         (++) BRERxStop                 (RX stopped or not upon Bit Rising Error)
164         (++) BREErrorBitGen            (Error-Bit generation in case of Bit Rising Error)
165         (++) LBPEErrorBitGen           (Error-Bit generation in case of Long Bit Period Error)
166         (++) BroadcastMsgNoErrorBitGen (Error-bit generation in case of broadcast message error)
167         (++) SignalFreeTimeOption      (SFT Timer start definition)
168         (++) OwnAddress                (CEC device address)
169         (++) ListenMode
170 
171 @endverbatim
172   * @{
173   */
174 
175 /**
176   * @brief Initializes the CEC mode according to the specified
177   *         parameters in the CEC_InitTypeDef and creates the associated handle .
178   * @param hcec CEC handle
179   * @retval HAL status
180   */
HAL_CEC_Init(CEC_HandleTypeDef * hcec)181 HAL_StatusTypeDef HAL_CEC_Init(CEC_HandleTypeDef *hcec)
182 {
183   /* Check the CEC handle allocation */
184   if ((hcec == NULL) || (hcec->Init.RxBuffer == NULL))
185   {
186     return HAL_ERROR;
187   }
188 
189   /* Check the parameters */
190   assert_param(IS_CEC_ALL_INSTANCE(hcec->Instance));
191   assert_param(IS_CEC_SIGNALFREETIME(hcec->Init.SignalFreeTime));
192   assert_param(IS_CEC_TOLERANCE(hcec->Init.Tolerance));
193   assert_param(IS_CEC_BRERXSTOP(hcec->Init.BRERxStop));
194   assert_param(IS_CEC_BREERRORBITGEN(hcec->Init.BREErrorBitGen));
195   assert_param(IS_CEC_LBPEERRORBITGEN(hcec->Init.LBPEErrorBitGen));
196   assert_param(IS_CEC_BROADCASTERROR_NO_ERRORBIT_GENERATION(hcec->Init.BroadcastMsgNoErrorBitGen));
197   assert_param(IS_CEC_SFTOP(hcec->Init.SignalFreeTimeOption));
198   assert_param(IS_CEC_LISTENING_MODE(hcec->Init.ListenMode));
199   assert_param(IS_CEC_OWN_ADDRESS(hcec->Init.OwnAddress));
200 
201 #if (USE_HAL_CEC_REGISTER_CALLBACKS == 1)
202   if (hcec->gState == HAL_CEC_STATE_RESET)
203   {
204     /* Allocate lock resource and initialize it */
205     hcec->Lock = HAL_UNLOCKED;
206 
207     hcec->TxCpltCallback  = HAL_CEC_TxCpltCallback;  /* Legacy weak TxCpltCallback  */
208     hcec->RxCpltCallback = HAL_CEC_RxCpltCallback;   /* Legacy weak RxCpltCallback */
209     hcec->ErrorCallback = HAL_CEC_ErrorCallback;     /* Legacy weak ErrorCallback */
210 
211     if (hcec->MspInitCallback == NULL)
212     {
213       hcec->MspInitCallback = HAL_CEC_MspInit; /* Legacy weak MspInit  */
214     }
215 
216     /* Init the low level hardware */
217     hcec->MspInitCallback(hcec);
218   }
219 #else
220   if (hcec->gState == HAL_CEC_STATE_RESET)
221   {
222     /* Allocate lock resource and initialize it */
223     hcec->Lock = HAL_UNLOCKED;
224     /* Init the low level hardware : GPIO, CLOCK */
225     HAL_CEC_MspInit(hcec);
226   }
227 #endif /* USE_HAL_CEC_REGISTER_CALLBACKS */
228 
229   hcec->gState = HAL_CEC_STATE_BUSY;
230 
231   /* Disable the Peripheral */
232   __HAL_CEC_DISABLE(hcec);
233 
234   /* Write to CEC Control Register */
235   hcec->Instance->CFGR = hcec->Init.SignalFreeTime | hcec->Init.Tolerance | hcec->Init.BRERxStop | \
236                          hcec->Init.BREErrorBitGen | hcec->Init.LBPEErrorBitGen | hcec->Init.BroadcastMsgNoErrorBitGen | \
237                          hcec->Init.SignalFreeTimeOption | ((uint32_t)(hcec->Init.OwnAddress) << 16U) | \
238                          hcec->Init.ListenMode;
239 
240   /* Enable the following CEC Transmission/Reception interrupts as
241     * well as the following CEC Transmission/Reception Errors interrupts
242     * Rx Byte Received IT
243     * End of Reception IT
244     * Rx overrun
245     * Rx bit rising error
246     * Rx short bit period error
247     * Rx long bit period error
248     * Rx missing acknowledge
249     * Tx Byte Request IT
250     * End of Transmission IT
251     * Tx Missing Acknowledge IT
252     * Tx-Error IT
253     * Tx-Buffer Underrun IT
254     * Tx arbitration lost   */
255   __HAL_CEC_ENABLE_IT(hcec, CEC_IT_RXBR | CEC_IT_RXEND | CEC_IER_RX_ALL_ERR | CEC_IT_TXBR | CEC_IT_TXEND |
256                       CEC_IER_TX_ALL_ERR);
257 
258   /* Enable the CEC Peripheral */
259   __HAL_CEC_ENABLE(hcec);
260 
261   hcec->ErrorCode = HAL_CEC_ERROR_NONE;
262   hcec->gState = HAL_CEC_STATE_READY;
263   hcec->RxState = HAL_CEC_STATE_READY;
264 
265   return HAL_OK;
266 }
267 
268 /**
269   * @brief DeInitializes the CEC peripheral
270   * @param hcec CEC handle
271   * @retval HAL status
272   */
HAL_CEC_DeInit(CEC_HandleTypeDef * hcec)273 HAL_StatusTypeDef HAL_CEC_DeInit(CEC_HandleTypeDef *hcec)
274 {
275   /* Check the CEC handle allocation */
276   if (hcec == NULL)
277   {
278     return HAL_ERROR;
279   }
280 
281   /* Check the parameters */
282   assert_param(IS_CEC_ALL_INSTANCE(hcec->Instance));
283 
284   hcec->gState = HAL_CEC_STATE_BUSY;
285 
286 #if (USE_HAL_CEC_REGISTER_CALLBACKS == 1)
287   if (hcec->MspDeInitCallback == NULL)
288   {
289     hcec->MspDeInitCallback = HAL_CEC_MspDeInit; /* Legacy weak MspDeInit  */
290   }
291 
292   /* DeInit the low level hardware */
293   hcec->MspDeInitCallback(hcec);
294 
295 #else
296   /* DeInit the low level hardware */
297   HAL_CEC_MspDeInit(hcec);
298 #endif /* USE_HAL_CEC_REGISTER_CALLBACKS */
299 
300   /* Disable the Peripheral */
301   __HAL_CEC_DISABLE(hcec);
302 
303   /* Clear Flags */
304   __HAL_CEC_CLEAR_FLAG(hcec, CEC_FLAG_TXEND | CEC_FLAG_TXBR | CEC_FLAG_RXBR | CEC_FLAG_RXEND | CEC_ISR_ALL_ERROR);
305 
306   /* Disable the following CEC Transmission/Reception interrupts as
307     * well as the following CEC Transmission/Reception Errors interrupts
308     * Rx Byte Received IT
309     * End of Reception IT
310     * Rx overrun
311     * Rx bit rising error
312     * Rx short bit period error
313     * Rx long bit period error
314     * Rx missing acknowledge
315     * Tx Byte Request IT
316     * End of Transmission IT
317     * Tx Missing Acknowledge IT
318     * Tx-Error IT
319     * Tx-Buffer Underrun IT
320     * Tx arbitration lost   */
321   __HAL_CEC_DISABLE_IT(hcec, CEC_IT_RXBR | CEC_IT_RXEND | CEC_IER_RX_ALL_ERR | CEC_IT_TXBR | CEC_IT_TXEND |
322                        CEC_IER_TX_ALL_ERR);
323 
324   hcec->ErrorCode = HAL_CEC_ERROR_NONE;
325   hcec->gState = HAL_CEC_STATE_RESET;
326   hcec->RxState = HAL_CEC_STATE_RESET;
327 
328   /* Process Unlock */
329   __HAL_UNLOCK(hcec);
330 
331   return HAL_OK;
332 }
333 
334 /**
335   * @brief Initializes the Own Address of the CEC device
336   * @param hcec CEC handle
337   * @param  CEC_OwnAddress The CEC own address.
338   * @retval HAL status
339   */
HAL_CEC_SetDeviceAddress(CEC_HandleTypeDef * hcec,uint16_t CEC_OwnAddress)340 HAL_StatusTypeDef HAL_CEC_SetDeviceAddress(CEC_HandleTypeDef *hcec, uint16_t CEC_OwnAddress)
341 {
342   /* Check the parameters */
343   assert_param(IS_CEC_OWN_ADDRESS(CEC_OwnAddress));
344 
345   if ((hcec->gState == HAL_CEC_STATE_READY) && (hcec->RxState == HAL_CEC_STATE_READY))
346   {
347     /* Process Locked */
348     __HAL_LOCK(hcec);
349 
350     hcec->gState = HAL_CEC_STATE_BUSY;
351 
352     /* Disable the Peripheral */
353     __HAL_CEC_DISABLE(hcec);
354 
355     if (CEC_OwnAddress != CEC_OWN_ADDRESS_NONE)
356     {
357       hcec->Instance->CFGR |= ((uint32_t)CEC_OwnAddress << 16);
358     }
359     else
360     {
361       hcec->Instance->CFGR &= ~(CEC_CFGR_OAR);
362     }
363 
364     hcec->gState = HAL_CEC_STATE_READY;
365     hcec->ErrorCode = HAL_CEC_ERROR_NONE;
366 
367     /* Process Unlocked */
368     __HAL_UNLOCK(hcec);
369 
370     /* Enable the Peripheral */
371     __HAL_CEC_ENABLE(hcec);
372 
373     return  HAL_OK;
374   }
375   else
376   {
377     return HAL_BUSY;
378   }
379 }
380 
381 /**
382   * @brief CEC MSP Init
383   * @param hcec CEC handle
384   * @retval None
385   */
HAL_CEC_MspInit(CEC_HandleTypeDef * hcec)386 __weak void HAL_CEC_MspInit(CEC_HandleTypeDef *hcec)
387 {
388   /* Prevent unused argument(s) compilation warning */
389   UNUSED(hcec);
390   /* NOTE : This function should not be modified, when the callback is needed,
391             the HAL_CEC_MspInit can be implemented in the user file
392    */
393 }
394 
395 /**
396   * @brief CEC MSP DeInit
397   * @param hcec CEC handle
398   * @retval None
399   */
HAL_CEC_MspDeInit(CEC_HandleTypeDef * hcec)400 __weak void HAL_CEC_MspDeInit(CEC_HandleTypeDef *hcec)
401 {
402   /* Prevent unused argument(s) compilation warning */
403   UNUSED(hcec);
404   /* NOTE : This function should not be modified, when the callback is needed,
405             the HAL_CEC_MspDeInit can be implemented in the user file
406    */
407 }
408 #if (USE_HAL_CEC_REGISTER_CALLBACKS == 1)
409 /**
410   * @brief  Register a User CEC Callback
411   *         To be used instead of the weak predefined callback
412   * @param  hcec CEC handle
413   * @param  CallbackID ID of the callback to be registered
414   *         This parameter can be one of the following values:
415   *          @arg @ref HAL_CEC_TX_CPLT_CB_ID Tx Complete callback ID
416   *          @arg @ref HAL_CEC_ERROR_CB_ID Error callback ID
417   *          @arg @ref HAL_CEC_MSPINIT_CB_ID MspInit callback ID
418   *          @arg @ref HAL_CEC_MSPDEINIT_CB_ID MspDeInit callback ID
419   * @param  pCallback pointer to the Callback function
420   * @retval HAL status
421   */
HAL_CEC_RegisterCallback(CEC_HandleTypeDef * hcec,HAL_CEC_CallbackIDTypeDef CallbackID,pCEC_CallbackTypeDef pCallback)422 HAL_StatusTypeDef HAL_CEC_RegisterCallback(CEC_HandleTypeDef *hcec, HAL_CEC_CallbackIDTypeDef CallbackID,
423                                            pCEC_CallbackTypeDef pCallback)
424 {
425   HAL_StatusTypeDef status = HAL_OK;
426 
427   if (pCallback == NULL)
428   {
429     /* Update the error code */
430     hcec->ErrorCode |= HAL_CEC_ERROR_INVALID_CALLBACK;
431     return HAL_ERROR;
432   }
433   /* Process locked */
434   __HAL_LOCK(hcec);
435 
436   if (hcec->gState == HAL_CEC_STATE_READY)
437   {
438     switch (CallbackID)
439     {
440       case HAL_CEC_TX_CPLT_CB_ID :
441         hcec->TxCpltCallback = pCallback;
442         break;
443 
444       case HAL_CEC_ERROR_CB_ID :
445         hcec->ErrorCallback = pCallback;
446         break;
447 
448       case HAL_CEC_MSPINIT_CB_ID :
449         hcec->MspInitCallback = pCallback;
450         break;
451 
452       case HAL_CEC_MSPDEINIT_CB_ID :
453         hcec->MspDeInitCallback = pCallback;
454         break;
455 
456       default :
457         /* Update the error code */
458         hcec->ErrorCode |= HAL_CEC_ERROR_INVALID_CALLBACK;
459         /* Return error status */
460         status =  HAL_ERROR;
461         break;
462     }
463   }
464   else if (hcec->gState == HAL_CEC_STATE_RESET)
465   {
466     switch (CallbackID)
467     {
468       case HAL_CEC_MSPINIT_CB_ID :
469         hcec->MspInitCallback = pCallback;
470         break;
471 
472       case HAL_CEC_MSPDEINIT_CB_ID :
473         hcec->MspDeInitCallback = pCallback;
474         break;
475 
476       default :
477         /* Update the error code */
478         hcec->ErrorCode |= HAL_CEC_ERROR_INVALID_CALLBACK;
479         /* Return error status */
480         status =  HAL_ERROR;
481         break;
482     }
483   }
484   else
485   {
486     /* Update the error code */
487     hcec->ErrorCode |= HAL_CEC_ERROR_INVALID_CALLBACK;
488     /* Return error status */
489     status =  HAL_ERROR;
490   }
491 
492   /* Release Lock */
493   __HAL_UNLOCK(hcec);
494 
495   return status;
496 }
497 
498 /**
499   * @brief  Unregister an CEC Callback
500   *         CEC callabck is redirected to the weak predefined callback
501   * @param hcec uart handle
502   * @param CallbackID ID of the callback to be unregistered
503   *         This parameter can be one of the following values:
504   *          @arg @ref HAL_CEC_TX_CPLT_CB_ID Tx Complete callback ID
505   *          @arg @ref HAL_CEC_ERROR_CB_ID Error callback ID
506   *          @arg @ref HAL_CEC_MSPINIT_CB_ID MspInit callback ID
507   *          @arg @ref HAL_CEC_MSPDEINIT_CB_ID MspDeInit callback ID
508   * @retval status
509   */
HAL_CEC_UnRegisterCallback(CEC_HandleTypeDef * hcec,HAL_CEC_CallbackIDTypeDef CallbackID)510 HAL_StatusTypeDef HAL_CEC_UnRegisterCallback(CEC_HandleTypeDef *hcec, HAL_CEC_CallbackIDTypeDef CallbackID)
511 {
512   HAL_StatusTypeDef status = HAL_OK;
513 
514   /* Process locked */
515   __HAL_LOCK(hcec);
516 
517   if (hcec->gState == HAL_CEC_STATE_READY)
518   {
519     switch (CallbackID)
520     {
521       case HAL_CEC_TX_CPLT_CB_ID :
522         hcec->TxCpltCallback = HAL_CEC_TxCpltCallback;  /* Legacy weak  TxCpltCallback */
523         break;
524 
525       case HAL_CEC_ERROR_CB_ID :
526         hcec->ErrorCallback = HAL_CEC_ErrorCallback;  /* Legacy weak ErrorCallback   */
527         break;
528 
529       case HAL_CEC_MSPINIT_CB_ID :
530         hcec->MspInitCallback = HAL_CEC_MspInit;
531         break;
532 
533       case HAL_CEC_MSPDEINIT_CB_ID :
534         hcec->MspDeInitCallback = HAL_CEC_MspDeInit;
535         break;
536 
537       default :
538         /* Update the error code */
539         hcec->ErrorCode |= HAL_CEC_ERROR_INVALID_CALLBACK;
540         /* Return error status */
541         status =  HAL_ERROR;
542         break;
543     }
544   }
545   else if (hcec->gState == HAL_CEC_STATE_RESET)
546   {
547     switch (CallbackID)
548     {
549       case HAL_CEC_MSPINIT_CB_ID :
550         hcec->MspInitCallback = HAL_CEC_MspInit;
551         break;
552 
553       case HAL_CEC_MSPDEINIT_CB_ID :
554         hcec->MspDeInitCallback = HAL_CEC_MspDeInit;
555         break;
556 
557       default :
558         /* Update the error code */
559         hcec->ErrorCode |= HAL_CEC_ERROR_INVALID_CALLBACK;
560         /* Return error status */
561         status =  HAL_ERROR;
562         break;
563     }
564   }
565   else
566   {
567     /* Update the error code */
568     hcec->ErrorCode |= HAL_CEC_ERROR_INVALID_CALLBACK;
569     /* Return error status */
570     status =  HAL_ERROR;
571   }
572 
573   /* Release Lock */
574   __HAL_UNLOCK(hcec);
575 
576   return status;
577 }
578 
579 /**
580   * @brief  Register CEC RX complete Callback
581   *         To be used instead of the weak HAL_CEC_RxCpltCallback() predefined callback
582   * @param  hcec CEC handle
583   * @param  pCallback pointer to the Rx transfer compelete Callback function
584   * @retval HAL status
585   */
HAL_CEC_RegisterRxCpltCallback(CEC_HandleTypeDef * hcec,pCEC_RxCallbackTypeDef pCallback)586 HAL_StatusTypeDef HAL_CEC_RegisterRxCpltCallback(CEC_HandleTypeDef *hcec, pCEC_RxCallbackTypeDef pCallback)
587 {
588   HAL_StatusTypeDef status = HAL_OK;
589 
590   if (pCallback == NULL)
591   {
592     /* Update the error code */
593     hcec->ErrorCode |= HAL_CEC_ERROR_INVALID_CALLBACK;
594     return HAL_ERROR;
595   }
596   /* Process locked */
597   __HAL_LOCK(hcec);
598 
599   if (HAL_CEC_STATE_READY == hcec->RxState)
600   {
601     hcec->RxCpltCallback = pCallback;
602   }
603   else
604   {
605     /* Update the error code */
606     hcec->ErrorCode |= HAL_CEC_ERROR_INVALID_CALLBACK;
607     /* Return error status */
608     status =  HAL_ERROR;
609   }
610 
611   /* Release Lock */
612   __HAL_UNLOCK(hcec);
613   return status;
614 }
615 
616 /**
617   * @brief  UnRegister CEC RX complete Callback
618   *         CEC RX complete Callback is redirected to the weak HAL_CEC_RxCpltCallback() predefined callback
619   * @param  hcec CEC handle
620   * @retval HAL status
621   */
HAL_CEC_UnRegisterRxCpltCallback(CEC_HandleTypeDef * hcec)622 HAL_StatusTypeDef HAL_CEC_UnRegisterRxCpltCallback(CEC_HandleTypeDef *hcec)
623 {
624   HAL_StatusTypeDef status = HAL_OK;
625 
626   /* Process locked */
627   __HAL_LOCK(hcec);
628 
629   if (HAL_CEC_STATE_READY == hcec->RxState)
630   {
631     hcec->RxCpltCallback = HAL_CEC_RxCpltCallback; /* Legacy weak  CEC RxCpltCallback  */
632   }
633   else
634   {
635     /* Update the error code */
636     hcec->ErrorCode |= HAL_CEC_ERROR_INVALID_CALLBACK;
637     /* Return error status */
638     status =  HAL_ERROR;
639   }
640 
641   /* Release Lock */
642   __HAL_UNLOCK(hcec);
643   return status;
644 }
645 #endif /* USE_HAL_CEC_REGISTER_CALLBACKS */
646 
647 /**
648   * @}
649   */
650 
651 /** @defgroup CEC_Exported_Functions_Group2 Input and Output operation functions
652   *  @brief CEC Transmit/Receive functions
653   *
654 @verbatim
655  ===============================================================================
656                       ##### IO operation functions #####
657  ===============================================================================
658     This subsection provides a set of functions allowing to manage the CEC data transfers.
659 
660     (#) The CEC handle must contain the initiator (TX side) and the destination (RX side)
661         logical addresses (4-bit long addresses, 0xF for broadcast messages destination)
662 
663     (#) The communication is performed using Interrupts.
664            These API's return the HAL status.
665            The end of the data processing will be indicated through the
666            dedicated CEC IRQ when using Interrupt mode.
667            The HAL_CEC_TxCpltCallback(), HAL_CEC_RxCpltCallback() user callbacks
668            will be executed respectively at the end of the transmit or Receive process
669            The HAL_CEC_ErrorCallback() user callback will be executed when a communication
670            error is detected
671 
672     (#) API's with Interrupt are :
673          (+) HAL_CEC_Transmit_IT()
674          (+) HAL_CEC_IRQHandler()
675 
676     (#) A set of User Callbacks are provided:
677          (+) HAL_CEC_TxCpltCallback()
678          (+) HAL_CEC_RxCpltCallback()
679          (+) HAL_CEC_ErrorCallback()
680 
681 @endverbatim
682   * @{
683   */
684 
685 /**
686   * @brief Send data in interrupt mode
687   * @param hcec CEC handle
688   * @param InitiatorAddress Initiator address
689   * @param DestinationAddress destination logical address
690   * @param pData pointer to input byte data buffer
691   * @param Size amount of data to be sent in bytes (without counting the header).
692   *              0 means only the header is sent (ping operation).
693   *              Maximum TX size is 15 bytes (1 opcode and up to 14 operands).
694   * @retval HAL status
695   */
HAL_CEC_Transmit_IT(CEC_HandleTypeDef * hcec,uint8_t InitiatorAddress,uint8_t DestinationAddress,uint8_t * pData,uint32_t Size)696 HAL_StatusTypeDef HAL_CEC_Transmit_IT(CEC_HandleTypeDef *hcec, uint8_t InitiatorAddress, uint8_t DestinationAddress,
697                                       uint8_t *pData, uint32_t Size)
698 {
699   /* if the IP isn't already busy and if there is no previous transmission
700      already pending due to arbitration lost */
701   if (hcec->gState == HAL_CEC_STATE_READY)
702   {
703     if ((pData == NULL) && (Size > 0U))
704     {
705       return  HAL_ERROR;
706     }
707 
708     assert_param(IS_CEC_ADDRESS(DestinationAddress));
709     assert_param(IS_CEC_ADDRESS(InitiatorAddress));
710     assert_param(IS_CEC_MSGSIZE(Size));
711 
712     /* Process Locked */
713     __HAL_LOCK(hcec);
714     hcec->pTxBuffPtr = pData;
715     hcec->gState = HAL_CEC_STATE_BUSY_TX;
716     hcec->ErrorCode = HAL_CEC_ERROR_NONE;
717 
718     /* initialize the number of bytes to send,
719       * 0 means only one header is sent (ping operation) */
720     hcec->TxXferCount = (uint16_t)Size;
721 
722     /* in case of no payload (Size = 0), sender is only pinging the system;
723        Set TX End of Message (TXEOM) bit, must be set before writing data to TXDR */
724     if (Size == 0U)
725     {
726       __HAL_CEC_LAST_BYTE_TX_SET(hcec);
727     }
728 
729     /* send header block */
730     hcec->Instance->TXDR = (uint32_t)(((uint32_t)InitiatorAddress << CEC_INITIATOR_LSB_POS) | DestinationAddress);
731 
732     /* Set TX Start of Message  (TXSOM) bit */
733     __HAL_CEC_FIRST_BYTE_TX_SET(hcec);
734 
735     /* Process Unlocked */
736     __HAL_UNLOCK(hcec);
737 
738     return HAL_OK;
739 
740   }
741   else
742   {
743     return HAL_BUSY;
744   }
745 }
746 
747 /**
748   * @brief Get size of the received frame.
749   * @param hcec CEC handle
750   * @retval Frame size
751   */
HAL_CEC_GetLastReceivedFrameSize(CEC_HandleTypeDef * hcec)752 uint32_t HAL_CEC_GetLastReceivedFrameSize(CEC_HandleTypeDef *hcec)
753 {
754   return hcec->RxXferSize;
755 }
756 
757 /**
758   * @brief Change Rx Buffer.
759   * @param hcec CEC handle
760   * @param Rxbuffer Rx Buffer
761   * @note  This function can be called only inside the HAL_CEC_RxCpltCallback()
762   * @retval Frame size
763   */
HAL_CEC_ChangeRxBuffer(CEC_HandleTypeDef * hcec,uint8_t * Rxbuffer)764 void HAL_CEC_ChangeRxBuffer(CEC_HandleTypeDef *hcec, uint8_t *Rxbuffer)
765 {
766   hcec->Init.RxBuffer = Rxbuffer;
767 }
768 
769 /**
770   * @brief This function handles CEC interrupt requests.
771   * @param hcec CEC handle
772   * @retval None
773   */
HAL_CEC_IRQHandler(CEC_HandleTypeDef * hcec)774 void HAL_CEC_IRQHandler(CEC_HandleTypeDef *hcec)
775 {
776 
777   /* save interrupts register for further error or interrupts handling purposes */
778   uint32_t reg;
779   reg = hcec->Instance->ISR;
780 
781 
782   /* ----------------------------Arbitration Lost Management----------------------------------*/
783   /* CEC TX arbitration error interrupt occurred --------------------------------------*/
784   if ((reg & CEC_FLAG_ARBLST) != 0U)
785   {
786     hcec->ErrorCode = HAL_CEC_ERROR_ARBLST;
787     __HAL_CEC_CLEAR_FLAG(hcec, CEC_FLAG_ARBLST);
788   }
789 
790   /* ----------------------------Rx Management----------------------------------*/
791   /* CEC RX byte received interrupt  ---------------------------------------------------*/
792   if ((reg & CEC_FLAG_RXBR) != 0U)
793   {
794     /* reception is starting */
795     hcec->RxState = HAL_CEC_STATE_BUSY_RX;
796     hcec->RxXferSize++;
797     /* read received byte */
798     *hcec->Init.RxBuffer = (uint8_t) hcec->Instance->RXDR;
799     hcec->Init.RxBuffer++;
800     __HAL_CEC_CLEAR_FLAG(hcec, CEC_FLAG_RXBR);
801   }
802 
803   /* CEC RX end received interrupt  ---------------------------------------------------*/
804   if ((reg & CEC_FLAG_RXEND) != 0U)
805   {
806     /* clear IT */
807     __HAL_CEC_CLEAR_FLAG(hcec, CEC_FLAG_RXEND);
808 
809     /* Rx process is completed, restore hcec->RxState to Ready */
810     hcec->RxState = HAL_CEC_STATE_READY;
811     hcec->ErrorCode = HAL_CEC_ERROR_NONE;
812     hcec->Init.RxBuffer -= hcec->RxXferSize;
813 #if (USE_HAL_CEC_REGISTER_CALLBACKS == 1U)
814     hcec->RxCpltCallback(hcec, hcec->RxXferSize);
815 #else
816     HAL_CEC_RxCpltCallback(hcec, hcec->RxXferSize);
817 #endif /* USE_HAL_CEC_REGISTER_CALLBACKS */
818     hcec->RxXferSize = 0U;
819   }
820 
821   /* ----------------------------Tx Management----------------------------------*/
822   /* CEC TX byte request interrupt ------------------------------------------------*/
823   if ((reg & CEC_FLAG_TXBR) != 0U)
824   {
825     if (hcec->TxXferCount == 0U)
826     {
827       /* if this is the last byte transmission, set TX End of Message (TXEOM) bit */
828       __HAL_CEC_LAST_BYTE_TX_SET(hcec);
829       hcec->Instance->TXDR = *hcec->pTxBuffPtr;
830       hcec->pTxBuffPtr++;
831     }
832     else
833     {
834       hcec->Instance->TXDR = *hcec->pTxBuffPtr;
835       hcec->pTxBuffPtr++;
836       hcec->TxXferCount--;
837     }
838     /* clear Tx-Byte request flag */
839     __HAL_CEC_CLEAR_FLAG(hcec, CEC_FLAG_TXBR);
840   }
841 
842   /* CEC TX end interrupt ------------------------------------------------*/
843   if ((reg & CEC_FLAG_TXEND) != 0U)
844   {
845     __HAL_CEC_CLEAR_FLAG(hcec, CEC_FLAG_TXEND);
846 
847     /* Tx process is ended, restore hcec->gState to Ready */
848     hcec->gState = HAL_CEC_STATE_READY;
849     /* Call the Process Unlocked before calling the Tx call back API to give the possibility to
850     start again the Transmission under the Tx call back API */
851     __HAL_UNLOCK(hcec);
852     hcec->ErrorCode = HAL_CEC_ERROR_NONE;
853 #if (USE_HAL_CEC_REGISTER_CALLBACKS == 1U)
854     hcec->TxCpltCallback(hcec);
855 #else
856     HAL_CEC_TxCpltCallback(hcec);
857 #endif /* USE_HAL_CEC_REGISTER_CALLBACKS */
858   }
859 
860   /* ----------------------------Rx/Tx Error Management----------------------------------*/
861   if ((reg & (CEC_ISR_RXOVR | CEC_ISR_BRE | CEC_ISR_SBPE | CEC_ISR_LBPE | CEC_ISR_RXACKE | CEC_ISR_TXUDR | CEC_ISR_TXERR |
862               CEC_ISR_TXACKE)) != 0U)
863   {
864     hcec->ErrorCode = reg;
865     __HAL_CEC_CLEAR_FLAG(hcec, HAL_CEC_ERROR_RXOVR | HAL_CEC_ERROR_BRE | CEC_FLAG_LBPE | CEC_FLAG_SBPE |
866                          HAL_CEC_ERROR_RXACKE | HAL_CEC_ERROR_TXUDR | HAL_CEC_ERROR_TXERR | HAL_CEC_ERROR_TXACKE);
867 
868 
869     if ((reg & (CEC_ISR_RXOVR | CEC_ISR_BRE | CEC_ISR_SBPE | CEC_ISR_LBPE | CEC_ISR_RXACKE)) != 0U)
870     {
871       hcec->Init.RxBuffer -= hcec->RxXferSize;
872       hcec->RxXferSize = 0U;
873       hcec->RxState = HAL_CEC_STATE_READY;
874     }
875     else if (((reg & CEC_ISR_ARBLST) == 0U) && ((reg & (CEC_ISR_TXUDR | CEC_ISR_TXERR | CEC_ISR_TXACKE)) != 0U))
876     {
877       /* Set the CEC state ready to be able to start again the process */
878       hcec->gState = HAL_CEC_STATE_READY;
879     }
880     else
881     {
882       /* Nothing todo*/
883     }
884 #if (USE_HAL_CEC_REGISTER_CALLBACKS == 1U)
885     hcec->ErrorCallback(hcec);
886 #else
887     /* Error  Call Back */
888     HAL_CEC_ErrorCallback(hcec);
889 #endif /* USE_HAL_CEC_REGISTER_CALLBACKS */
890   }
891   else
892   {
893     /* Nothing todo*/
894   }
895 }
896 
897 /**
898   * @brief Tx Transfer completed callback
899   * @param hcec CEC handle
900   * @retval None
901   */
HAL_CEC_TxCpltCallback(CEC_HandleTypeDef * hcec)902 __weak void HAL_CEC_TxCpltCallback(CEC_HandleTypeDef *hcec)
903 {
904   /* Prevent unused argument(s) compilation warning */
905   UNUSED(hcec);
906   /* NOTE : This function should not be modified, when the callback is needed,
907             the HAL_CEC_TxCpltCallback can be implemented in the user file
908    */
909 }
910 
911 /**
912   * @brief Rx Transfer completed callback
913   * @param hcec CEC handle
914   * @param RxFrameSize Size of frame
915   * @retval None
916   */
HAL_CEC_RxCpltCallback(CEC_HandleTypeDef * hcec,uint32_t RxFrameSize)917 __weak void HAL_CEC_RxCpltCallback(CEC_HandleTypeDef *hcec, uint32_t RxFrameSize)
918 {
919   /* Prevent unused argument(s) compilation warning */
920   UNUSED(hcec);
921   UNUSED(RxFrameSize);
922   /* NOTE : This function should not be modified, when the callback is needed,
923             the HAL_CEC_RxCpltCallback can be implemented in the user file
924    */
925 }
926 
927 /**
928   * @brief CEC error callbacks
929   * @param hcec CEC handle
930   * @retval None
931   */
HAL_CEC_ErrorCallback(CEC_HandleTypeDef * hcec)932 __weak void HAL_CEC_ErrorCallback(CEC_HandleTypeDef *hcec)
933 {
934   /* Prevent unused argument(s) compilation warning */
935   UNUSED(hcec);
936   /* NOTE : This function should not be modified, when the callback is needed,
937             the HAL_CEC_ErrorCallback can be implemented in the user file
938    */
939 }
940 /**
941   * @}
942   */
943 
944 /** @defgroup CEC_Exported_Functions_Group3 Peripheral Control function
945   *  @brief   CEC control functions
946   *
947 @verbatim
948  ===============================================================================
949                       ##### Peripheral Control function #####
950  ===============================================================================
951     [..]
952     This subsection provides a set of functions allowing to control the CEC.
953      (+) HAL_CEC_GetState() API can be helpful to check in run-time the state of the CEC peripheral.
954      (+) HAL_CEC_GetError() API can be helpful to check in run-time the error of the CEC peripheral.
955 @endverbatim
956   * @{
957   */
958 /**
959   * @brief return the CEC state
960   * @param hcec pointer to a CEC_HandleTypeDef structure that contains
961   *              the configuration information for the specified CEC module.
962   * @retval HAL state
963   */
HAL_CEC_GetState(CEC_HandleTypeDef * hcec)964 HAL_CEC_StateTypeDef HAL_CEC_GetState(CEC_HandleTypeDef *hcec)
965 {
966   uint32_t temp1, temp2;
967   temp1 = hcec->gState;
968   temp2 = hcec->RxState;
969 
970   return (HAL_CEC_StateTypeDef)(temp1 | temp2);
971 }
972 
973 /**
974   * @brief  Return the CEC error code
975   * @param  hcec  pointer to a CEC_HandleTypeDef structure that contains
976   *              the configuration information for the specified CEC.
977   * @retval CEC Error Code
978   */
HAL_CEC_GetError(CEC_HandleTypeDef * hcec)979 uint32_t HAL_CEC_GetError(CEC_HandleTypeDef *hcec)
980 {
981   return hcec->ErrorCode;
982 }
983 
984 /**
985   * @}
986   */
987 
988 /**
989   * @}
990   */
991 #endif /* CEC */
992 #endif /* HAL_CEC_MODULE_ENABLED */
993 /**
994   * @}
995   */
996 
997 /**
998   * @}
999   */
1000