summaryrefslogtreecommitdiffstats
path: root/bsps/arm/stm32h7/hal/stm32h7xx_hal_dsi.c
diff options
context:
space:
mode:
Diffstat (limited to 'bsps/arm/stm32h7/hal/stm32h7xx_hal_dsi.c')
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_hal_dsi.c627
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>&copy; 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****/