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