diff options
Diffstat (limited to 'bsps/arm/stm32h7/hal/stm32h7xx_hal_dsi.c')
-rw-r--r-- | bsps/arm/stm32h7/hal/stm32h7xx_hal_dsi.c | 627 |
1 files changed, 520 insertions, 107 deletions
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_hal_dsi.c b/bsps/arm/stm32h7/hal/stm32h7xx_hal_dsi.c index 8156e0beb4..7e8f109c57 100644 --- a/bsps/arm/stm32h7/hal/stm32h7xx_hal_dsi.c +++ b/bsps/arm/stm32h7/hal/stm32h7xx_hal_dsi.c @@ -9,40 +9,72 @@ * + IO operation functions * + Peripheral Control functions * + Peripheral State and Errors functions + ****************************************************************************** + * @attention + * + * Copyright (c) 2017 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** @verbatim ============================================================================== ##### How to use this driver ##### ============================================================================== + [..] + The DSI HAL driver can be used as follows: + + (#) Declare a DSI_HandleTypeDef handle structure, for example: DSI_HandleTypeDef hdsi; + + (#) Initialize the DSI low level resources by implementing the HAL_DSI_MspInit() API: + (##) Enable the DSI interface clock + (##) NVIC configuration if you need to use interrupt process + (+++) Configure the DSI interrupt priority + (+++) Enable the NVIC DSI IRQ Channel + + (#) Initialize the DSI Host peripheral, the required PLL parameters, number of lances and + TX Escape clock divider by calling the HAL_DSI_Init() API which calls HAL_DSI_MspInit(). + + *** Configuration *** + ========================= [..] - (#) Use @ref HAL_DSI_Init() function to initialize the DSI Host IP and program the required - PLL parameters, number of lanes and TX Escape clock divider. - (#) Use @ref HAL_DSI_ConfigAdaptedCommandMode() function to configure the DSI host in adapted + (#) Use HAL_DSI_ConfigAdaptedCommandMode() function to configure the DSI host in adapted command mode. - (#) When operating in video mode , use @ref HAL_DSI_ConfigVideoMode() to configure the DSI host. - (#) Function @ref HAL_DSI_ConfigCommand() is used to configure the DSI commands behavior in low power mode. - (#) To configure the DSI PHY timings parameters, use function @ref HAL_DSI_ConfigPhyTimer(). - (#) The DSI Host can be started/stopped using respectively functions @ref HAL_DSI_Start() and @ref HAL_DSI_Stop(). - Functions @ref HAL_DSI_ShortWrite(), @ref HAL_DSI_LongWrite() and @ref HAL_DSI_Read() allows respectively + + (#) When operating in video mode , use HAL_DSI_ConfigVideoMode() to configure the DSI host. + + (#) Function HAL_DSI_ConfigCommand() is used to configure the DSI commands behavior in low power mode. + + (#) To configure the DSI PHY timings parameters, use function HAL_DSI_ConfigPhyTimer(). + + (#) The DSI Host can be started/stopped using respectively functions HAL_DSI_Start() and HAL_DSI_Stop(). + Functions HAL_DSI_ShortWrite(), HAL_DSI_LongWrite() and HAL_DSI_Read() allows respectively to write DSI short packets, long packets and to read DSI packets. (#) The DSI Host Offers two Low power modes : - (+) Low Power Mode on data lanes only: Only DSI data lanes are shut down. - It is possible to enter/exit from this mode using respectively functions @ref HAL_DSI_EnterULPMData() - and @ref HAL_DSI_ExitULPMData() - - (+) Low Power Mode on data and clock lanes : All DSI lanes are shut down including data and clock lanes. - It is possible to enter/exit from this mode using respectively functions @ref HAL_DSI_EnterULPM() - and @ref HAL_DSI_ExitULPM() + (++) Low Power Mode on data lanes only: Only DSI data lanes are shut down. + It is possible to enter/exit from this mode using respectively functions HAL_DSI_EnterULPMData() + and HAL_DSI_ExitULPMData() - (#) User can select the DSI errors to be reported/monitored using function @ref HAL_DSI_ConfigErrorMonitor() - When an error occurs, the callback @ref HAL_DSI_ErrorCallback() is asserted and then user can retrieve - the error code by calling function @ref HAL_DSI_GetError() + (++) Low Power Mode on data and clock lanes : All DSI lanes are shut down including data and clock lanes. + It is possible to enter/exit from this mode using respectively functions HAL_DSI_EnterULPM() + and HAL_DSI_ExitULPM() (#) To control DSI state you can use the following function: HAL_DSI_GetState() - *** DSI HAL driver macros list *** - ============================================= - [..] + *** Error management *** + ======================== + [..] + (#) User can select the DSI errors to be reported/monitored using function HAL_DSI_ConfigErrorMonitor() + When an error occurs, the callback HAL_DSI_ErrorCallback() is asserted and then user can retrieve + the error code by calling function HAL_DSI_GetError() + + *** DSI HAL driver macros list *** + ============================================= + [..] Below the list of most used macros in DSI HAL driver. (+) __HAL_DSI_ENABLE: Enable the DSI Host. @@ -59,72 +91,66 @@ (+) __HAL_DSI_DISABLE_IT: Disables the specified DSI interrupts. (+) __HAL_DSI_GET_IT_SOURCE: Checks whether the specified DSI interrupt source is enabled or not. + [..] + (@) You can refer to the DSI HAL driver header file for more useful macros + *** Callback registration *** + ============================================= + [..] + The compilation define USE_HAL_DSI_REGISTER_CALLBACKS when set to 1 + allows the user to configure dynamically the driver callbacks. + Use Function HAL_DSI_RegisterCallback() to register a callback. - *** Callback registration *** - ============================================= - - The compilation define USE_HAL_DSI_REGISTER_CALLBACKS when set to 1 - allows the user to configure dynamically the driver callbacks. - Use Function @ref HAL_DSI_RegisterCallback() to register a callback. - - Function @ref HAL_DSI_RegisterCallback() allows to register following callbacks: - (+) TearingEffectCallback : DSI Tearing Effect Callback. - (+) EndOfRefreshCallback : DSI End Of Refresh Callback. - (+) ErrorCallback : DSI Error Callback - (+) MspInitCallback : DSI MspInit. - (+) MspDeInitCallback : DSI MspDeInit. - This function takes as parameters the HAL peripheral handle, the Callback ID - and a pointer to the user callback function. - - Use function @ref HAL_DSI_UnRegisterCallback() to reset a callback to the default - weak function. - @ref HAL_DSI_UnRegisterCallback takes as parameters the HAL peripheral handle, - and the Callback ID. - This function allows to reset following callbacks: - (+) TearingEffectCallback : DSI Tearing Effect Callback. - (+) EndOfRefreshCallback : DSI End Of Refresh Callback. - (+) ErrorCallback : DSI Error Callback - (+) MspInitCallback : DSI MspInit. - (+) MspDeInitCallback : DSI MspDeInit. - - By default, after the HAL_DSI_Init and when the state is HAL_DSI_STATE_RESET - all callbacks are set to the corresponding weak functions: - examples @ref HAL_DSI_TearingEffectCallback(), @ref HAL_DSI_EndOfRefreshCallback(). - Exception done for MspInit and MspDeInit functions that are - reset to the legacy weak function in the HAL_DSI_Init/ @ref HAL_DSI_DeInit only when - these callbacks are null (not registered beforehand). - if not, MspInit or MspDeInit are not null, the @ref HAL_DSI_Init/ @ref HAL_DSI_DeInit - keep and use the user MspInit/MspDeInit callbacks (registered beforehand) - - Callbacks can be registered/unregistered in HAL_DSI_STATE_READY state only. - Exception done MspInit/MspDeInit that can be registered/unregistered - in HAL_DSI_STATE_READY or HAL_DSI_STATE_RESET state, - thus registered (user) MspInit/DeInit callbacks can be used during the Init/DeInit. - In that case first register the MspInit/MspDeInit user callbacks - using @ref HAL_DSI_RegisterCallback() before calling @ref HAL_DSI_DeInit - or HAL_DSI_Init function. - - When The compilation define USE_HAL_DSI_REGISTER_CALLBACKS is set to 0 or - not defined, the callback registration feature is not available and all callbacks - are set to the corresponding weak functions. - - [..] - (@) You can refer to the DSI HAL driver header file for more useful macros + [..] + Function HAL_DSI_RegisterCallback() allows to register following callbacks: + (+) TearingEffectCallback : DSI Tearing Effect Callback. + (+) EndOfRefreshCallback : DSI End Of Refresh Callback. + (+) ErrorCallback : DSI Error Callback + (+) MspInitCallback : DSI MspInit. + (+) MspDeInitCallback : DSI MspDeInit. + [..] + This function takes as parameters the HAL peripheral handle, the callback ID + and a pointer to the user callback function. + + [..] + Use function HAL_DSI_UnRegisterCallback() to reset a callback to the default + weak function. + HAL_DSI_UnRegisterCallback takes as parameters the HAL peripheral handle, + and the callback ID. + [..] + This function allows to reset following callbacks: + (+) TearingEffectCallback : DSI Tearing Effect Callback. + (+) EndOfRefreshCallback : DSI End Of Refresh Callback. + (+) ErrorCallback : DSI Error Callback + (+) MspInitCallback : DSI MspInit. + (+) MspDeInitCallback : DSI MspDeInit. + + [..] + By default, after the HAL_DSI_Init and when the state is HAL_DSI_STATE_RESET + all callbacks are set to the corresponding weak functions: + examples HAL_DSI_TearingEffectCallback(), HAL_DSI_EndOfRefreshCallback(). + Exception done for MspInit and MspDeInit functions that are respectively + reset to the legacy weak (surcharged) functions in the HAL_DSI_Init() + and HAL_DSI_DeInit() only when these callbacks are null (not registered beforehand). + If not, MspInit or MspDeInit are not null, the HAL_DSI_Init() and HAL_DSI_DeInit() + keep and use the user MspInit/MspDeInit callbacks (registered beforehand). + + [..] + Callbacks can be registered/unregistered in HAL_DSI_STATE_READY state only. + Exception done MspInit/MspDeInit that can be registered/unregistered + in HAL_DSI_STATE_READY or HAL_DSI_STATE_RESET state, + thus registered (user) MspInit/DeInit callbacks can be used during the Init/DeInit. + In that case first register the MspInit/MspDeInit user callbacks + using HAL_DSI_RegisterCallback() before calling HAL_DSI_DeInit() + or HAL_DSI_Init() function. + + [..] + When The compilation define USE_HAL_DSI_REGISTER_CALLBACKS is set to 0 or + not defined, the callback registration feature is not available and all callbacks + are set to the corresponding weak functions. @endverbatim ****************************************************************************** - * @attention - * - * <h2><center>© Copyright (c) 2017 STMicroelectronics. - * All rights reserved.</center></h2> - * - * This software component is licensed by ST under BSD 3-Clause license, - * the "License"; You may not use this file except in compliance with the - * License. You may obtain a copy of the License at: - * opensource.org/licenses/BSD-3-Clause - * - ****************************************************************************** */ /* Includes ------------------------------------------------------------------*/ @@ -174,12 +200,15 @@ static void DSI_ConfigPacketHeader(DSI_TypeDef *DSIx, uint32_t ChannelID, uint32 uint32_t Data1); static HAL_StatusTypeDef DSI_ShortWrite(DSI_HandleTypeDef *hdsi, - uint32_t ChannelID, - uint32_t Mode, - uint32_t Param1, - uint32_t Param2); - + uint32_t ChannelID, + uint32_t Mode, + uint32_t Param1, + uint32_t Param2); /* Private functions ---------------------------------------------------------*/ +/** @defgroup DSI_Private_Functions DSI Private Functions + * @ingroup RTEMSBSPsARMSTM32H7 + * @{ + */ /** * @brief Generic DSI packet header configuration * @param DSIx Pointer to DSI register base @@ -229,10 +258,10 @@ static HAL_StatusTypeDef DSI_ShortWrite(DSI_HandleTypeDef *hdsi, tickstart = HAL_GetTick(); /* Wait for Command FIFO Empty */ - while((hdsi->Instance->GPSR & DSI_GPSR_CMDFE) == 0U) + while ((hdsi->Instance->GPSR & DSI_GPSR_CMDFE) == 0U) { /* Check for the Timeout */ - if((HAL_GetTick() - tickstart ) > DSI_TIMEOUT_VALUE) + if ((HAL_GetTick() - tickstart) > DSI_TIMEOUT_VALUE) { return HAL_TIMEOUT; } @@ -245,6 +274,10 @@ static HAL_StatusTypeDef DSI_ShortWrite(DSI_HandleTypeDef *hdsi, return HAL_OK; } +/** + * @} + */ + /* Exported functions --------------------------------------------------------*/ /** @addtogroup DSI_Exported_Functions * @{ @@ -340,11 +373,17 @@ HAL_StatusTypeDef HAL_DSI_Init(DSI_HandleTypeDef *hdsi, DSI_PLLInitTypeDef *PLLI /* Set the PLL division factors */ hdsi->Instance->WRPCR &= ~(DSI_WRPCR_PLL_NDIV | DSI_WRPCR_PLL_IDF | DSI_WRPCR_PLL_ODF); - hdsi->Instance->WRPCR |= (((PLLInit->PLLNDIV) << 2U) | ((PLLInit->PLLIDF) << 11U) | ((PLLInit->PLLODF) << 16U)); + hdsi->Instance->WRPCR |= (((PLLInit->PLLNDIV) << DSI_WRPCR_PLL_NDIV_Pos) | \ + ((PLLInit->PLLIDF) << DSI_WRPCR_PLL_IDF_Pos) | \ + ((PLLInit->PLLODF) << DSI_WRPCR_PLL_ODF_Pos)); /* Enable the DSI PLL */ __HAL_DSI_PLL_ENABLE(hdsi); + /* Requires min of 400us delay before reading the PLLLS flag */ + /* 1ms delay is inserted that is the minimum HAL delay granularity */ + HAL_Delay(1); + /* Get tick */ tickstart = HAL_GetTick(); @@ -394,7 +433,7 @@ HAL_StatusTypeDef HAL_DSI_Init(DSI_HandleTypeDef *hdsi, DSI_PLLInitTypeDef *PLLI hdsi->Instance->IER[1U] = 0U; hdsi->ErrorMsk = 0U; - /* Initialise the error code */ + /* Initialize the error code */ hdsi->ErrorCode = HAL_DSI_ERROR_NONE; /* Initialize the DSI state*/ @@ -448,7 +487,7 @@ HAL_StatusTypeDef HAL_DSI_DeInit(DSI_HandleTypeDef *hdsi) HAL_DSI_MspDeInit(hdsi); #endif /* USE_HAL_DSI_REGISTER_CALLBACKS */ - /* Initialise the error code */ + /* Initialize the error code */ hdsi->ErrorCode = HAL_DSI_ERROR_NONE; /* Initialize the DSI state*/ @@ -673,7 +712,7 @@ HAL_StatusTypeDef HAL_DSI_RegisterCallback(DSI_HandleTypeDef *hdsi, HAL_DSI_Call /** * @brief Unregister a DSI Callback - * DSI callabck is redirected to the weak predefined callback + * DSI callback is redirected to the weak predefined callback * @param hdsi dsi handle * @param CallbackID ID of the callback to be unregistered * This parameter can be one of the following values: @@ -708,11 +747,11 @@ HAL_StatusTypeDef HAL_DSI_UnRegisterCallback(DSI_HandleTypeDef *hdsi, HAL_DSI_Ca break; case HAL_DSI_MSPINIT_CB_ID : - hdsi->MspInitCallback = HAL_DSI_MspInit; /* Legcay weak MspInit Callback */ + hdsi->MspInitCallback = HAL_DSI_MspInit; /* Legacy weak MspInit Callback */ break; case HAL_DSI_MSPDEINIT_CB_ID : - hdsi->MspDeInitCallback = HAL_DSI_MspDeInit; /* Legcay weak MspDeInit Callback */ + hdsi->MspDeInitCallback = HAL_DSI_MspDeInit; /* Legacy weak MspDeInit Callback */ break; default : @@ -728,11 +767,11 @@ HAL_StatusTypeDef HAL_DSI_UnRegisterCallback(DSI_HandleTypeDef *hdsi, HAL_DSI_Ca switch (CallbackID) { case HAL_DSI_MSPINIT_CB_ID : - hdsi->MspInitCallback = HAL_DSI_MspInit; /* Legcay weak MspInit Callback */ + hdsi->MspInitCallback = HAL_DSI_MspInit; /* Legacy weak MspInit Callback */ break; case HAL_DSI_MSPDEINIT_CB_ID : - hdsi->MspDeInitCallback = HAL_DSI_MspDeInit; /* Legcay weak MspDeInit Callback */ + hdsi->MspDeInitCallback = HAL_DSI_MspDeInit; /* Legacy weak MspDeInit Callback */ break; default : @@ -784,7 +823,8 @@ HAL_StatusTypeDef HAL_DSI_UnRegisterCallback(DSI_HandleTypeDef *hdsi, HAL_DSI_Ca */ void HAL_DSI_IRQHandler(DSI_HandleTypeDef *hdsi) { - uint32_t ErrorStatus0, ErrorStatus1; + uint32_t ErrorStatus0; + uint32_t ErrorStatus1; /* Tearing Effect Interrupt management ***************************************/ if (__HAL_DSI_GET_FLAG(hdsi, DSI_FLAG_TE) != 0U) @@ -1342,7 +1382,8 @@ HAL_StatusTypeDef HAL_DSI_ConfigPhyTimer(DSI_HandleTypeDef *hdsi, DSI_PHY_TimerT High-Speed transmission. To do so, the DSI Host calculates the time required for the clock lane to change from HighSpeed to Low-Power and from Low-Power to High-Speed. - This timings are configured by the HS2LP_TIME and LP2HS_TIME in the DSI Host Clock Lane Timer Configuration Register (DSI_CLTCR). + This timings are configured by the HS2LP_TIME and LP2HS_TIME in the DSI Host Clock Lane Timer Configuration + Register (DSI_CLTCR). But the DSI Host is not calculating LP2HS_TIME + HS2LP_TIME but 2 x HS2LP_TIME. Workaround : Configure HS2LP_TIME and LP2HS_TIME with the same value being the max of HS2LP_TIME or LP2HS_TIME. @@ -1564,7 +1605,7 @@ HAL_StatusTypeDef HAL_DSI_ShortWrite(DSI_HandleTypeDef *hdsi, /* Process locked */ __HAL_LOCK(hdsi); - status = DSI_ShortWrite(hdsi, ChannelID, Mode, Param1, Param2); + status = DSI_ShortWrite(hdsi, ChannelID, Mode, Param1, Param2); /* Process unlocked */ __HAL_UNLOCK(hdsi); @@ -1593,7 +1634,9 @@ HAL_StatusTypeDef HAL_DSI_LongWrite(DSI_HandleTypeDef *hdsi, uint32_t Param1, uint8_t *ParametersTable) { - uint32_t uicounter, nbBytes, count; + uint32_t uicounter; + uint32_t nbBytes; + uint32_t count; uint32_t tickstart; uint32_t fifoword; uint8_t *pparams = ParametersTable; @@ -1698,7 +1741,7 @@ HAL_StatusTypeDef HAL_DSI_Read(DSI_HandleTypeDef *hdsi, { /* set max return packet size */ if (DSI_ShortWrite(hdsi, ChannelNbr, DSI_MAX_RETURN_PKT_SIZE, ((datasize) & 0xFFU), - (((datasize) >> 8U) & 0xFFU)) != HAL_OK) + (((datasize) >> 8U) & 0xFFU)) != HAL_OK) { /* Process Unlocked */ __HAL_UNLOCK(hdsi); @@ -1759,6 +1802,21 @@ HAL_StatusTypeDef HAL_DSI_Read(DSI_HandleTypeDef *hdsi, return HAL_TIMEOUT; } + + /* Software workaround to avoid HAL_TIMEOUT when a DSI read command is */ + /* issued to the panel and the read data is not captured by the DSI Host */ + /* which returns Packet Size Error. */ + /* Need to ensure that the Read command has finished before checking PSE */ + if ((hdsi->Instance->GPSR & DSI_GPSR_RCB) == 0U) + { + if ((hdsi->Instance->ISR[1U] & DSI_ISR1_PSE) == DSI_ISR1_PSE) + { + /* Process Unlocked */ + __HAL_UNLOCK(hdsi); + + return HAL_ERROR; + } + } } /* Process unlocked */ @@ -1781,6 +1839,85 @@ HAL_StatusTypeDef HAL_DSI_EnterULPMData(DSI_HandleTypeDef *hdsi) /* Process locked */ __HAL_LOCK(hdsi); + /* Verify the initial status of the DSI Host */ + + /* Verify that the clock lane and the digital section of the D-PHY are enabled */ + if ((hdsi->Instance->PCTLR & (DSI_PCTLR_CKE | DSI_PCTLR_DEN)) != (DSI_PCTLR_CKE | DSI_PCTLR_DEN)) + { + /* Process Unlocked */ + __HAL_UNLOCK(hdsi); + return HAL_ERROR; + } + + /* Verify that the D-PHY PLL and the reference bias are enabled */ + if ((hdsi->Instance->WRPCR & DSI_WRPCR_PLLEN) != DSI_WRPCR_PLLEN) + { + /* Process Unlocked */ + __HAL_UNLOCK(hdsi); + return HAL_ERROR; + } + + /* Verify that there are no ULPS exit or request on data lanes */ + if ((hdsi->Instance->PUCR & (DSI_PUCR_UEDL | DSI_PUCR_URDL)) != 0U) + { + /* Process Unlocked */ + __HAL_UNLOCK(hdsi); + return HAL_ERROR; + } + + /* Verify that there are no Transmission trigger */ + if ((hdsi->Instance->PTTCR & DSI_PTTCR_TX_TRIG) != 0U) + { + /* Process Unlocked */ + __HAL_UNLOCK(hdsi); + return HAL_ERROR; + } + + /* Requires min of 400us delay before reading the PLLLS flag */ + /* 1ms delay is inserted that is the minimum HAL delay granularity */ + HAL_Delay(1); + + /* Verify that D-PHY PLL is locked */ + tickstart = HAL_GetTick(); + + while ((__HAL_DSI_GET_FLAG(hdsi, DSI_FLAG_PLLLS) == 0U)) + { + /* Check for the Timeout */ + if ((HAL_GetTick() - tickstart) > DSI_TIMEOUT_VALUE) + { + /* Process Unlocked */ + __HAL_UNLOCK(hdsi); + + return HAL_TIMEOUT; + } + } + + /* Verify that all active lanes are in Stop state */ + if ((hdsi->Instance->PCONFR & DSI_PCONFR_NL) == DSI_ONE_DATA_LANE) + { + if ((hdsi->Instance->PSR & DSI_PSR_UAN0) != DSI_PSR_UAN0) + { + /* Process Unlocked */ + __HAL_UNLOCK(hdsi); + return HAL_ERROR; + } + } + else if ((hdsi->Instance->PCONFR & DSI_PCONFR_NL) == DSI_TWO_DATA_LANES) + { + if ((hdsi->Instance->PSR & (DSI_PSR_UAN0 | DSI_PSR_UAN1)) != (DSI_PSR_UAN0 | DSI_PSR_UAN1)) + { + /* Process Unlocked */ + __HAL_UNLOCK(hdsi); + return HAL_ERROR; + } + } + else + { + /* Process unlocked */ + __HAL_UNLOCK(hdsi); + return HAL_ERROR; + } + /* ULPS Request on Data Lanes */ hdsi->Instance->PUCR |= DSI_PUCR_URDL; @@ -1844,6 +1981,58 @@ HAL_StatusTypeDef HAL_DSI_ExitULPMData(DSI_HandleTypeDef *hdsi) /* Process locked */ __HAL_LOCK(hdsi); + /* Verify that all active lanes are in ULPM */ + if ((hdsi->Instance->PCONFR & DSI_PCONFR_NL) == DSI_ONE_DATA_LANE) + { + if ((hdsi->Instance->PSR & DSI_PSR_UAN0) != 0U) + { + /* Process Unlocked */ + __HAL_UNLOCK(hdsi); + + return HAL_ERROR; + } + } + else if ((hdsi->Instance->PCONFR & DSI_PCONFR_NL) == DSI_TWO_DATA_LANES) + { + if ((hdsi->Instance->PSR & (DSI_PSR_UAN0 | DSI_PSR_UAN1)) != 0U) + { + /* Process Unlocked */ + __HAL_UNLOCK(hdsi); + + return HAL_ERROR; + } + } + else + { + /* Process unlocked */ + __HAL_UNLOCK(hdsi); + + return HAL_ERROR; + } + + /* Turn on the DSI PLL */ + __HAL_DSI_PLL_ENABLE(hdsi); + + /* Requires min of 400us delay before reading the PLLLS flag */ + /* 1ms delay is inserted that is the minimum HAL delay granularity */ + HAL_Delay(1); + + /* Get tick */ + tickstart = HAL_GetTick(); + + /* Wait for the lock of the PLL */ + while (__HAL_DSI_GET_FLAG(hdsi, DSI_FLAG_PLLLS) == 0U) + { + /* Check for the Timeout */ + if ((HAL_GetTick() - tickstart) > DSI_TIMEOUT_VALUE) + { + /* Process Unlocked */ + __HAL_UNLOCK(hdsi); + + return HAL_TIMEOUT; + } + } + /* Exit ULPS on Data Lanes */ hdsi->Instance->PUCR |= DSI_PUCR_UEDL; @@ -1893,6 +2082,61 @@ HAL_StatusTypeDef HAL_DSI_ExitULPMData(DSI_HandleTypeDef *hdsi) /* De-assert the ULPM requests and the ULPM exit bits */ hdsi->Instance->PUCR = 0U; + /* Verify that D-PHY PLL is enabled */ + if ((hdsi->Instance->WRPCR & DSI_WRPCR_PLLEN) != DSI_WRPCR_PLLEN) + { + /* Process Unlocked */ + __HAL_UNLOCK(hdsi); + return HAL_ERROR; + } + + /* Verify that all active lanes are in Stop state */ + if ((hdsi->Instance->PCONFR & DSI_PCONFR_NL) == DSI_ONE_DATA_LANE) + { + if ((hdsi->Instance->PSR & DSI_PSR_UAN0) != DSI_PSR_UAN0) + { + /* Process Unlocked */ + __HAL_UNLOCK(hdsi); + return HAL_ERROR; + } + } + else if ((hdsi->Instance->PCONFR & DSI_PCONFR_NL) == DSI_TWO_DATA_LANES) + { + if ((hdsi->Instance->PSR & (DSI_PSR_UAN0 | DSI_PSR_UAN1)) != (DSI_PSR_UAN0 | DSI_PSR_UAN1)) + { + /* Process Unlocked */ + __HAL_UNLOCK(hdsi); + return HAL_ERROR; + } + } + else + { + /* Process unlocked */ + __HAL_UNLOCK(hdsi); + return HAL_ERROR; + } + + /* Verify that D-PHY PLL is locked */ + /* Requires min of 400us delay before reading the PLLLS flag */ + /* 1ms delay is inserted that is the minimum HAL delay granularity */ + HAL_Delay(1); + + /* Get tick */ + tickstart = HAL_GetTick(); + + /* Wait for the lock of the PLL */ + while (__HAL_DSI_GET_FLAG(hdsi, DSI_FLAG_PLLLS) == 0U) + { + /* Check for the Timeout */ + if ((HAL_GetTick() - tickstart) > DSI_TIMEOUT_VALUE) + { + /* Process Unlocked */ + __HAL_UNLOCK(hdsi); + + return HAL_TIMEOUT; + } + } + /* Process unlocked */ __HAL_UNLOCK(hdsi); @@ -1913,6 +2157,86 @@ HAL_StatusTypeDef HAL_DSI_EnterULPM(DSI_HandleTypeDef *hdsi) /* Process locked */ __HAL_LOCK(hdsi); + /* Verify the initial status of the DSI Host */ + + /* Verify that the clock lane and the digital section of the D-PHY are enabled */ + if ((hdsi->Instance->PCTLR & (DSI_PCTLR_CKE | DSI_PCTLR_DEN)) != (DSI_PCTLR_CKE | DSI_PCTLR_DEN)) + { + /* Process Unlocked */ + __HAL_UNLOCK(hdsi); + return HAL_ERROR; + } + + /* Verify that the D-PHY PLL and the reference bias are enabled */ + if ((hdsi->Instance->WRPCR & DSI_WRPCR_PLLEN) != DSI_WRPCR_PLLEN) + { + /* Process Unlocked */ + __HAL_UNLOCK(hdsi); + return HAL_ERROR; + } + + /* Verify that there are no ULPS exit or request on both data and clock lanes */ + if ((hdsi->Instance->PUCR & (DSI_PUCR_UEDL | DSI_PUCR_URDL | DSI_PUCR_UECL | DSI_PUCR_URCL)) != 0U) + { + /* Process Unlocked */ + __HAL_UNLOCK(hdsi); + return HAL_ERROR; + } + + /* Verify that there are no Transmission trigger */ + if ((hdsi->Instance->PTTCR & DSI_PTTCR_TX_TRIG) != 0U) + { + /* Process Unlocked */ + __HAL_UNLOCK(hdsi); + return HAL_ERROR; + } + + /* Requires min of 400us delay before reading the PLLLS flag */ + /* 1ms delay is inserted that is the minimum HAL delay granularity */ + HAL_Delay(1); + + /* Verify that D-PHY PLL is locked */ + tickstart = HAL_GetTick(); + + while ((__HAL_DSI_GET_FLAG(hdsi, DSI_FLAG_PLLLS) == 0U)) + { + /* Check for the Timeout */ + if ((HAL_GetTick() - tickstart) > DSI_TIMEOUT_VALUE) + { + /* Process Unlocked */ + __HAL_UNLOCK(hdsi); + + return HAL_TIMEOUT; + } + } + + /* Verify that all active lanes are in Stop state */ + if ((hdsi->Instance->PCONFR & DSI_PCONFR_NL) == DSI_ONE_DATA_LANE) + { + if ((hdsi->Instance->PSR & (DSI_PSR_UAN0 | DSI_PSR_PSS0)) != (DSI_PSR_UAN0 | DSI_PSR_PSS0)) + { + /* Process Unlocked */ + __HAL_UNLOCK(hdsi); + return HAL_ERROR; + } + } + else if ((hdsi->Instance->PCONFR & DSI_PCONFR_NL) == DSI_TWO_DATA_LANES) + { + if ((hdsi->Instance->PSR & (DSI_PSR_UAN0 | DSI_PSR_PSS0 | DSI_PSR_PSS1 | \ + DSI_PSR_UAN1)) != (DSI_PSR_UAN0 | DSI_PSR_PSS0 | DSI_PSR_PSS1 | DSI_PSR_UAN1)) + { + /* Process Unlocked */ + __HAL_UNLOCK(hdsi); + return HAL_ERROR; + } + } + else + { + /* Process unlocked */ + __HAL_UNLOCK(hdsi); + return HAL_ERROR; + } + /* Clock lane configuration: no more HS request */ hdsi->Instance->CLCR &= ~DSI_CLCR_DPCC; @@ -1925,7 +2249,7 @@ HAL_StatusTypeDef HAL_DSI_EnterULPM(DSI_HandleTypeDef *hdsi) /* Get tick */ tickstart = HAL_GetTick(); - /* Wait until all active lanes exit ULPM */ + /* Wait until all active lanes enter ULPM */ if ((hdsi->Instance->PCONFR & DSI_PCONFR_NL) == DSI_ONE_DATA_LANE) { while ((hdsi->Instance->PSR & (DSI_PSR_UAN0 | DSI_PSR_UANC)) != 0U) @@ -1985,9 +2309,44 @@ HAL_StatusTypeDef HAL_DSI_ExitULPM(DSI_HandleTypeDef *hdsi) /* Process locked */ __HAL_LOCK(hdsi); + /* Verify that all active lanes are in ULPM */ + if ((hdsi->Instance->PCONFR & DSI_PCONFR_NL) == DSI_ONE_DATA_LANE) + { + if ((hdsi->Instance->PSR & (DSI_PSR_RUE0 | DSI_PSR_UAN0 | DSI_PSR_PSS0 | \ + DSI_PSR_UANC | DSI_PSR_PSSC | DSI_PSR_PD)) != 0U) + { + /* Process Unlocked */ + __HAL_UNLOCK(hdsi); + + return HAL_ERROR; + } + } + else if ((hdsi->Instance->PCONFR & DSI_PCONFR_NL) == DSI_TWO_DATA_LANES) + { + if ((hdsi->Instance->PSR & (DSI_PSR_RUE0 | DSI_PSR_UAN0 | DSI_PSR_PSS0 | DSI_PSR_UAN1 | \ + DSI_PSR_PSS1 | DSI_PSR_UANC | DSI_PSR_PSSC | DSI_PSR_PD)) != 0U) + { + /* Process Unlocked */ + __HAL_UNLOCK(hdsi); + + return HAL_ERROR; + } + } + else + { + /* Process unlocked */ + __HAL_UNLOCK(hdsi); + + return HAL_ERROR; + } + /* Turn on the DSI PLL */ __HAL_DSI_PLL_ENABLE(hdsi); + /* Requires min of 400us delay before reading the PLLLS flag */ + /* 1ms delay is inserted that is the minimum HAL delay granularity */ + HAL_Delay(1); + /* Get tick */ tickstart = HAL_GetTick(); @@ -2054,12 +2413,68 @@ HAL_StatusTypeDef HAL_DSI_ExitULPM(DSI_HandleTypeDef *hdsi) /* De-assert the ULPM requests and the ULPM exit bits */ hdsi->Instance->PUCR = 0U; - /* Switch the lanbyteclock source in the RCC from system PLL to D-PHY */ + /* Switch the lane byte clock source in the RCC from system PLL to D-PHY */ __HAL_RCC_DSI_CONFIG(RCC_DSICLKSOURCE_PHY); /* Restore clock lane configuration to HS */ hdsi->Instance->CLCR |= DSI_CLCR_DPCC; + /* Verify that D-PHY PLL is enabled */ + if ((hdsi->Instance->WRPCR & DSI_WRPCR_PLLEN) != DSI_WRPCR_PLLEN) + { + /* Process Unlocked */ + __HAL_UNLOCK(hdsi); + return HAL_ERROR; + } + + /* Verify that all active lanes are in Stop state */ + if ((hdsi->Instance->PCONFR & DSI_PCONFR_NL) == DSI_ONE_DATA_LANE) + { + if ((hdsi->Instance->PSR & (DSI_PSR_UAN0 | DSI_PSR_PSS0)) != (DSI_PSR_UAN0 | DSI_PSR_PSS0)) + { + /* Process Unlocked */ + __HAL_UNLOCK(hdsi); + return HAL_ERROR; + } + } + else if ((hdsi->Instance->PCONFR & DSI_PCONFR_NL) == DSI_TWO_DATA_LANES) + { + if ((hdsi->Instance->PSR & (DSI_PSR_UAN0 | DSI_PSR_PSS0 | DSI_PSR_PSS1 | \ + DSI_PSR_UAN1)) != (DSI_PSR_UAN0 | DSI_PSR_PSS0 | DSI_PSR_PSS1 | DSI_PSR_UAN1)) + { + /* Process Unlocked */ + __HAL_UNLOCK(hdsi); + return HAL_ERROR; + } + } + else + { + /* Process unlocked */ + __HAL_UNLOCK(hdsi); + return HAL_ERROR; + } + + /* Verify that D-PHY PLL is locked */ + /* Requires min of 400us delay before reading the PLLLS flag */ + /* 1ms delay is inserted that is the minimum HAL delay granularity */ + HAL_Delay(1); + + /* Get tick */ + tickstart = HAL_GetTick(); + + /* Wait for the lock of the PLL */ + while (__HAL_DSI_GET_FLAG(hdsi, DSI_FLAG_PLLLS) == 0U) + { + /* Check for the Timeout */ + if ((HAL_GetTick() - tickstart) > DSI_TIMEOUT_VALUE) + { + /* Process Unlocked */ + __HAL_UNLOCK(hdsi); + + return HAL_TIMEOUT; + } + } + /* Process unlocked */ __HAL_UNLOCK(hdsi); @@ -2266,7 +2681,7 @@ HAL_StatusTypeDef HAL_DSI_SetSDD(DSI_HandleTypeDef *hdsi, FunctionalState State) * @brief Custom lane pins configuration * @param hdsi pointer to a DSI_HandleTypeDef structure that contains * the configuration information for the DSI. - * @param CustomLane Function to be applyed on selected lane. + * @param CustomLane Function to be applied on selected lane. * This parameter can be any value of @arg DSI_CustomLane * @param Lane select between clock or data lane 0 or data lane 1. * This parameter can be any value of @arg DSI_Lane_Select @@ -2705,5 +3120,3 @@ uint32_t HAL_DSI_GetError(DSI_HandleTypeDef *hdsi) /** * @} */ - -/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ |