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