update to CubeMX 6.14.0, FW_H7 1.12.1
This commit is contained in:
@ -115,7 +115,9 @@
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
#if defined(TAMP)
|
||||
#define TAMP_ALL (TAMP_CR1_TAMP1E | TAMP_CR1_TAMP2E | TAMP_CR1_TAMP3E)
|
||||
#endif /* TAMP */
|
||||
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
@ -469,7 +471,7 @@ HAL_StatusTypeDef HAL_RTCEx_GetTimeStamp(RTC_HandleTypeDef *hrtc, RTC_TimeTypeDe
|
||||
* @param sTamper Pointer to Tamper Structure.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_RTCEx_SetTamper(RTC_HandleTypeDef * hrtc, RTC_TamperTypeDef * sTamper)
|
||||
HAL_StatusTypeDef HAL_RTCEx_SetTamper(RTC_HandleTypeDef * hrtc, const RTC_TamperTypeDef * sTamper)
|
||||
{
|
||||
uint32_t tmpreg;
|
||||
|
||||
@ -537,7 +539,7 @@ HAL_StatusTypeDef HAL_RTCEx_SetTamper(RTC_HandleTypeDef * hrtc, RTC_TamperTypeDe
|
||||
* @param sTamper Pointer to Tamper Structure.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_RTCEx_SetTamper(RTC_HandleTypeDef * hrtc, RTC_TamperTypeDef * sTamper)
|
||||
HAL_StatusTypeDef HAL_RTCEx_SetTamper(RTC_HandleTypeDef * hrtc, const RTC_TamperTypeDef * sTamper)
|
||||
{
|
||||
uint32_t tmpreg;
|
||||
|
||||
@ -576,6 +578,7 @@ HAL_StatusTypeDef HAL_RTCEx_SetTamper(RTC_HandleTypeDef * hrtc, RTC_TamperTypeDe
|
||||
tmpreg &= (uint32_t)~(sTamper->Tamper << 1U);
|
||||
}
|
||||
|
||||
#if defined(RTC_TAMPNOERASE_SUPPORT)
|
||||
/* Configure the tamper backup registers erasure bit */
|
||||
if (sTamper->NoErase != RTC_TAMPER_ERASE_BACKUP_ENABLE)
|
||||
{
|
||||
@ -607,7 +610,9 @@ HAL_StatusTypeDef HAL_RTCEx_SetTamper(RTC_HandleTypeDef * hrtc, RTC_TamperTypeDe
|
||||
tmpreg &= (uint32_t)~(RTC_TAMPCR_TAMP3NOERASE);
|
||||
}
|
||||
}
|
||||
#endif /* RTC_TAMPNOERASE_SUPPORT */
|
||||
|
||||
#if defined(RTC_TAMPMASKFLAG_SUPPORT)
|
||||
/* Configure the tamper flags masking bit */
|
||||
if (sTamper->MaskFlag != RTC_TAMPERMASK_FLAG_DISABLE)
|
||||
{
|
||||
@ -639,6 +644,7 @@ HAL_StatusTypeDef HAL_RTCEx_SetTamper(RTC_HandleTypeDef * hrtc, RTC_TamperTypeDe
|
||||
tmpreg &= (uint32_t)~(RTC_TAMPCR_TAMP3MF);
|
||||
}
|
||||
}
|
||||
#endif /* RTC_TAMPMASKFLAG_SUPPORT */
|
||||
|
||||
/* Clearing remaining fields before setting them */
|
||||
tmpreg &= ~(RTC_TAMPERFILTER_MASK | RTC_TAMPERSAMPLINGFREQ_RTCCLK_MASK | \
|
||||
@ -671,7 +677,7 @@ HAL_StatusTypeDef HAL_RTCEx_SetTamper(RTC_HandleTypeDef * hrtc, RTC_TamperTypeDe
|
||||
* @param sTamper Pointer to Tamper Structure.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_RTCEx_SetTamper_IT(RTC_HandleTypeDef * hrtc, RTC_TamperTypeDef * sTamper)
|
||||
HAL_StatusTypeDef HAL_RTCEx_SetTamper_IT(RTC_HandleTypeDef * hrtc, const RTC_TamperTypeDef * sTamper)
|
||||
{
|
||||
uint32_t tmpreg;
|
||||
|
||||
@ -748,7 +754,7 @@ HAL_StatusTypeDef HAL_RTCEx_SetTamper_IT(RTC_HandleTypeDef * hrtc, RTC_TamperTyp
|
||||
* @param sTamper Pointer to Tamper Structure.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_RTCEx_SetTamper_IT(RTC_HandleTypeDef * hrtc, RTC_TamperTypeDef * sTamper)
|
||||
HAL_StatusTypeDef HAL_RTCEx_SetTamper_IT(RTC_HandleTypeDef * hrtc, const RTC_TamperTypeDef * sTamper)
|
||||
{
|
||||
uint32_t tmpreg;
|
||||
|
||||
@ -788,6 +794,7 @@ HAL_StatusTypeDef HAL_RTCEx_SetTamper_IT(RTC_HandleTypeDef * hrtc, RTC_TamperTyp
|
||||
tmpreg &= (uint32_t)~(sTamper->Tamper << 1U);
|
||||
}
|
||||
|
||||
#if defined(RTC_TAMPNOERASE_SUPPORT)
|
||||
/* Configure the tamper backup registers erasure bit */
|
||||
if (sTamper->NoErase != RTC_TAMPER_ERASE_BACKUP_ENABLE)
|
||||
{
|
||||
@ -819,7 +826,9 @@ HAL_StatusTypeDef HAL_RTCEx_SetTamper_IT(RTC_HandleTypeDef * hrtc, RTC_TamperTyp
|
||||
tmpreg &= (uint32_t)~(RTC_TAMPCR_TAMP3NOERASE);
|
||||
}
|
||||
}
|
||||
#endif /* RTC_TAMPNOERASE_SUPPORT */
|
||||
|
||||
#if defined(RTC_TAMPMASKFLAG_SUPPORT)
|
||||
/* Configure the tamper flags masking bit */
|
||||
if (sTamper->MaskFlag != RTC_TAMPERMASK_FLAG_DISABLE)
|
||||
{
|
||||
@ -851,6 +860,7 @@ HAL_StatusTypeDef HAL_RTCEx_SetTamper_IT(RTC_HandleTypeDef * hrtc, RTC_TamperTyp
|
||||
tmpreg &= (uint32_t)~(RTC_TAMPCR_TAMP3MF);
|
||||
}
|
||||
}
|
||||
#endif /* RTC_TAMPMASKFLAG_SUPPORT */
|
||||
|
||||
/* Clearing remaining fields before setting them */
|
||||
tmpreg &= ~(RTC_TAMPERFILTER_MASK | RTC_TAMPERSAMPLINGFREQ_RTCCLK_MASK | \
|
||||
@ -933,8 +943,9 @@ HAL_StatusTypeDef HAL_RTCEx_DeactivateTamper(RTC_HandleTypeDef * hrtc, uint32_t
|
||||
* @param Tamper Selected tamper pin.
|
||||
* This parameter can be any combination of the following values:
|
||||
* @arg RTC_TAMPER_1
|
||||
* @arg RTC_TAMPER_2
|
||||
* @arg RTC_TAMPER_2 (*)
|
||||
* @arg RTC_TAMPER_3
|
||||
* (*) Not applicable to all devices.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_RTCEx_DeactivateTamper(RTC_HandleTypeDef * hrtc, uint32_t Tamper)
|
||||
@ -949,21 +960,28 @@ HAL_StatusTypeDef HAL_RTCEx_DeactivateTamper(RTC_HandleTypeDef * hrtc, uint32_t
|
||||
/* Disable the selected Tamper pin */
|
||||
hrtc->Instance->TAMPCR &= ((uint32_t)~Tamper);
|
||||
|
||||
#if defined(RTC_TAMPxIE_SUPPORT)
|
||||
/* Disable the selected Tamper interrupt */
|
||||
if ((Tamper & RTC_TAMPER_1) != 0U)
|
||||
{
|
||||
hrtc->Instance->TAMPCR &= ((uint32_t)~(RTC_IT_TAMP | RTC_IT_TAMP1));
|
||||
}
|
||||
|
||||
#if defined(RTC_TAMPER2_SUPPORT)
|
||||
if ((Tamper & RTC_TAMPER_2) != 0U)
|
||||
{
|
||||
hrtc->Instance->TAMPCR &= ((uint32_t)~(RTC_IT_TAMP | RTC_IT_TAMP2));
|
||||
}
|
||||
#endif /* RTC_TAMPER2_SUPPORT */
|
||||
|
||||
if ((Tamper & RTC_TAMPER_3) != 0U)
|
||||
{
|
||||
hrtc->Instance->TAMPCR &= ((uint32_t)~(RTC_IT_TAMP | RTC_IT_TAMP3));
|
||||
}
|
||||
#else
|
||||
/* Disable the Tamper interrupt */
|
||||
hrtc->Instance->TAMPCR &= (uint32_t)~(RTC_IT_TAMP);
|
||||
#endif /* RTC_TAMPxIE_SUPPORT */
|
||||
|
||||
hrtc->State = HAL_RTC_STATE_READY;
|
||||
|
||||
@ -981,7 +999,7 @@ HAL_StatusTypeDef HAL_RTCEx_DeactivateTamper(RTC_HandleTypeDef * hrtc, uint32_t
|
||||
* @param sIntTamper Pointer to Internal Tamper Structure.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_RTCEx_SetInternalTamper(RTC_HandleTypeDef *hrtc, RTC_InternalTamperTypeDef *sIntTamper)
|
||||
HAL_StatusTypeDef HAL_RTCEx_SetInternalTamper(RTC_HandleTypeDef *hrtc, const RTC_InternalTamperTypeDef *sIntTamper)
|
||||
{
|
||||
/* Check the parameters */
|
||||
assert_param(IS_RTC_INTERNAL_TAMPER(sIntTamper->IntTamper));
|
||||
@ -1007,7 +1025,7 @@ HAL_StatusTypeDef HAL_RTCEx_SetInternalTamper(RTC_HandleTypeDef *hrtc, RTC_Inter
|
||||
* @param sIntTamper Pointer to Internal Tamper Structure.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_RTCEx_SetInternalTamper_IT(RTC_HandleTypeDef *hrtc, RTC_InternalTamperTypeDef *sIntTamper)
|
||||
HAL_StatusTypeDef HAL_RTCEx_SetInternalTamper_IT(RTC_HandleTypeDef *hrtc, const RTC_InternalTamperTypeDef *sIntTamper)
|
||||
{
|
||||
/* Check the parameters */
|
||||
assert_param(IS_RTC_INTERNAL_TAMPER(sIntTamper->IntTamper));
|
||||
@ -1063,7 +1081,7 @@ HAL_StatusTypeDef HAL_RTCEx_DeactivateInternalTamper(RTC_HandleTypeDef *hrtc, ui
|
||||
* @param sAllTamper Pointer to active Tamper Structure.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_RTCEx_SetActiveTampers(RTC_HandleTypeDef *hrtc, RTC_ActiveTampersTypeDef *sAllTamper)
|
||||
HAL_StatusTypeDef HAL_RTCEx_SetActiveTampers(RTC_HandleTypeDef *hrtc, const RTC_ActiveTampersTypeDef *sAllTamper)
|
||||
{
|
||||
uint32_t IER, CR1, CR2, ATCR1, CR, i, tickstart;
|
||||
|
||||
@ -1177,7 +1195,7 @@ HAL_StatusTypeDef HAL_RTCEx_SetActiveTampers(RTC_HandleTypeDef *hrtc, RTC_Active
|
||||
* @param pSeed Pointer to active tamper seed values.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_RTCEx_SetActiveSeed(RTC_HandleTypeDef *hrtc, uint32_t *pSeed)
|
||||
HAL_StatusTypeDef HAL_RTCEx_SetActiveSeed(RTC_HandleTypeDef *hrtc, const uint32_t *pSeed)
|
||||
{
|
||||
uint32_t i, tickstart;
|
||||
|
||||
@ -1295,6 +1313,7 @@ void HAL_RTCEx_TamperTimeStampIRQHandler(RTC_HandleTypeDef *hrtc)
|
||||
#endif /* USE_HAL_RTC_REGISTER_CALLBACKS */
|
||||
}
|
||||
|
||||
#if defined(RTC_TAMPER2_SUPPORT)
|
||||
/* Check Tamper 2 status */
|
||||
if ((tmp & RTC_TAMPER_2) == RTC_TAMPER_2)
|
||||
{
|
||||
@ -1306,6 +1325,7 @@ void HAL_RTCEx_TamperTimeStampIRQHandler(RTC_HandleTypeDef *hrtc)
|
||||
HAL_RTCEx_Tamper2EventCallback(hrtc);
|
||||
#endif /* USE_HAL_RTC_REGISTER_CALLBACKS */
|
||||
}
|
||||
#endif /* RTC_TAMPER2_SUPPORT */
|
||||
|
||||
/* Check Tamper 3 status */
|
||||
if ((tmp & RTC_TAMPER_3) == RTC_TAMPER_3)
|
||||
@ -1442,7 +1462,11 @@ void HAL_RTCEx_TamperTimeStampIRQHandler(RTC_HandleTypeDef *hrtc)
|
||||
}
|
||||
|
||||
/* Get the Tamper 1 interrupt source enable status */
|
||||
#if defined(RTC_TAMPxIE_SUPPORT)
|
||||
if (__HAL_RTC_TAMPER_GET_IT_SOURCE(hrtc, RTC_IT_TAMP | RTC_IT_TAMP1) != 0U)
|
||||
#else
|
||||
if (__HAL_RTC_TAMPER_GET_IT_SOURCE(hrtc, RTC_IT_TAMP) != 0U)
|
||||
#endif /* RTC_TAMPxIE_SUPPORT */
|
||||
{
|
||||
/* Get the pending status of the Tamper 1 Interrupt */
|
||||
if (__HAL_RTC_TAMPER_GET_FLAG(hrtc, RTC_FLAG_TAMP1F) != 0U)
|
||||
@ -1460,7 +1484,12 @@ void HAL_RTCEx_TamperTimeStampIRQHandler(RTC_HandleTypeDef *hrtc)
|
||||
}
|
||||
|
||||
/* Get the Tamper 2 interrupt source enable status */
|
||||
#if defined(RTC_TAMPER2_SUPPORT)
|
||||
#if defined(RTC_TAMPxIE_SUPPORT)
|
||||
if (__HAL_RTC_TAMPER_GET_IT_SOURCE(hrtc, RTC_IT_TAMP | RTC_IT_TAMP2) != 0U)
|
||||
#else
|
||||
if (__HAL_RTC_TAMPER_GET_IT_SOURCE(hrtc, RTC_IT_TAMP) != 0U)
|
||||
#endif /* RTC_TAMPxIE_SUPPORT */
|
||||
{
|
||||
/* Get the pending status of the Tamper 2 Interrupt */
|
||||
if (__HAL_RTC_TAMPER_GET_FLAG(hrtc, RTC_FLAG_TAMP2F) != 0U)
|
||||
@ -1476,9 +1505,14 @@ void HAL_RTCEx_TamperTimeStampIRQHandler(RTC_HandleTypeDef *hrtc)
|
||||
#endif /* (USE_HAL_RTC_REGISTER_CALLBACKS == 1) */
|
||||
}
|
||||
}
|
||||
#endif /* RTC_TAMPER2_SUPPORT */
|
||||
|
||||
/* Get the Tamper 3 interrupts source enable status */
|
||||
#if defined(RTC_TAMPxIE_SUPPORT)
|
||||
if (__HAL_RTC_TAMPER_GET_IT_SOURCE(hrtc, RTC_IT_TAMP | RTC_IT_TAMP3) != 0U)
|
||||
#else
|
||||
if (__HAL_RTC_TAMPER_GET_IT_SOURCE(hrtc, RTC_IT_TAMP) != 0U)
|
||||
#endif /* RTC_TAMPxIE_SUPPORT */
|
||||
{
|
||||
/* Get the pending status of the Tamper 3 Interrupt */
|
||||
if (__HAL_RTC_TAMPER_GET_FLAG(hrtc, RTC_FLAG_TAMP3F) != 0U)
|
||||
@ -1540,6 +1574,7 @@ __weak void HAL_RTCEx_Tamper1EventCallback(RTC_HandleTypeDef * hrtc)
|
||||
*/
|
||||
}
|
||||
|
||||
#if defined(RTC_TAMPER2_SUPPORT)
|
||||
/**
|
||||
* @brief Tamper 2 callback.
|
||||
* @param hrtc RTC handle
|
||||
@ -1554,6 +1589,7 @@ __weak void HAL_RTCEx_Tamper2EventCallback(RTC_HandleTypeDef * hrtc)
|
||||
the HAL_RTCEx_Tamper2EventCallback could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
#endif /* RTC_TAMPER2_SUPPORT */
|
||||
|
||||
/**
|
||||
* @brief Tamper 3 callback.
|
||||
@ -1768,6 +1804,7 @@ HAL_StatusTypeDef HAL_RTCEx_PollForTamper1Event(RTC_HandleTypeDef * hrtc, uint32
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
#if defined(RTC_TAMPER2_SUPPORT)
|
||||
/**
|
||||
* @brief Handle Tamper2 Polling.
|
||||
* @param hrtc RTC handle
|
||||
@ -1799,6 +1836,7 @@ HAL_StatusTypeDef HAL_RTCEx_PollForTamper2Event(RTC_HandleTypeDef * hrtc, uint32
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
#endif /* RTC_TAMPER2_SUPPORT */
|
||||
|
||||
/**
|
||||
* @brief Handle Tamper3 Polling.
|
||||
@ -2129,7 +2167,7 @@ HAL_StatusTypeDef HAL_RTCEx_DeactivateWakeUpTimer(RTC_HandleTypeDef *hrtc)
|
||||
* @param hrtc RTC handle
|
||||
* @retval Counter value
|
||||
*/
|
||||
uint32_t HAL_RTCEx_GetWakeUpTimer(RTC_HandleTypeDef *hrtc)
|
||||
uint32_t HAL_RTCEx_GetWakeUpTimer(const RTC_HandleTypeDef *hrtc)
|
||||
{
|
||||
/* Get the counter value */
|
||||
return ((uint32_t)(hrtc->Instance->WUTR & RTC_WUTR_WUT));
|
||||
@ -2273,7 +2311,7 @@ HAL_StatusTypeDef HAL_RTCEx_PollForWakeUpTimerEvent(RTC_HandleTypeDef * hrtc, ui
|
||||
* @param Data Data to be written in the specified Backup data register.
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_RTCEx_BKUPWrite(RTC_HandleTypeDef * hrtc, uint32_t BackupRegister, uint32_t Data)
|
||||
void HAL_RTCEx_BKUPWrite(const RTC_HandleTypeDef * hrtc, uint32_t BackupRegister, uint32_t Data)
|
||||
{
|
||||
uint32_t tmp;
|
||||
|
||||
@ -2282,9 +2320,9 @@ void HAL_RTCEx_BKUPWrite(RTC_HandleTypeDef * hrtc, uint32_t BackupRegister, uint
|
||||
|
||||
/* Point on address of first backup register */
|
||||
#if defined(TAMP)
|
||||
tmp = (uint32_t) & (((TAMP_TypeDef *)((uint32_t)hrtc->Instance + TAMP_OFFSET))->BKP0R);
|
||||
tmp = (uint32_t) &(((TAMP_TypeDef *)((uint32_t)hrtc->Instance + TAMP_OFFSET))->BKP0R);
|
||||
#else
|
||||
tmp = (uint32_t) & (hrtc->Instance->BKP0R);
|
||||
tmp = (uint32_t) &(hrtc->Instance->BKP0R);
|
||||
#endif /* TAMP */
|
||||
|
||||
tmp += (BackupRegister * 4U);
|
||||
@ -2302,7 +2340,7 @@ void HAL_RTCEx_BKUPWrite(RTC_HandleTypeDef * hrtc, uint32_t BackupRegister, uint
|
||||
* specify the register.
|
||||
* @retval Read value
|
||||
*/
|
||||
uint32_t HAL_RTCEx_BKUPRead(RTC_HandleTypeDef * hrtc, uint32_t BackupRegister)
|
||||
uint32_t HAL_RTCEx_BKUPRead(const RTC_HandleTypeDef * hrtc, uint32_t BackupRegister)
|
||||
{
|
||||
uint32_t tmp;
|
||||
|
||||
@ -2311,9 +2349,9 @@ uint32_t HAL_RTCEx_BKUPRead(RTC_HandleTypeDef * hrtc, uint32_t BackupRegister)
|
||||
|
||||
/* Point on address of first backup register */
|
||||
#if defined(TAMP)
|
||||
tmp = (uint32_t) & (((TAMP_TypeDef *)((uint32_t)hrtc->Instance + TAMP_OFFSET))->BKP0R);
|
||||
tmp = (uint32_t) &(((TAMP_TypeDef *)((uint32_t)hrtc->Instance + TAMP_OFFSET))->BKP0R);
|
||||
#else
|
||||
tmp = (uint32_t) & (hrtc->Instance->BKP0R);
|
||||
tmp = (uint32_t) &(hrtc->Instance->BKP0R);
|
||||
#endif /* TAMP */
|
||||
|
||||
tmp += (BackupRegister * 4U);
|
||||
@ -2709,7 +2747,7 @@ HAL_StatusTypeDef HAL_RTCEx_EnableBypassShadow(RTC_HandleTypeDef * hrtc)
|
||||
__HAL_RTC_WRITEPROTECTION_DISABLE(hrtc);
|
||||
|
||||
/* Set the BYPSHAD bit */
|
||||
hrtc->Instance->CR |= (uint8_t)RTC_CR_BYPSHAD;
|
||||
hrtc->Instance->CR |= (uint32_t)RTC_CR_BYPSHAD;
|
||||
|
||||
/* Enable the write protection for RTC registers */
|
||||
__HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
|
||||
@ -2741,7 +2779,7 @@ HAL_StatusTypeDef HAL_RTCEx_DisableBypassShadow(RTC_HandleTypeDef * hrtc)
|
||||
__HAL_RTC_WRITEPROTECTION_DISABLE(hrtc);
|
||||
|
||||
/* Reset the BYPSHAD bit */
|
||||
hrtc->Instance->CR &= ((uint8_t)~RTC_CR_BYPSHAD);
|
||||
hrtc->Instance->CR &= ((uint32_t)~RTC_CR_BYPSHAD);
|
||||
|
||||
/* Enable the write protection for RTC registers */
|
||||
__HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
|
||||
@ -2784,7 +2822,7 @@ HAL_StatusTypeDef HAL_RTCEx_MonotonicCounterIncrement(RTC_HandleTypeDef *hrtc,
|
||||
* @param Counter monotonic counter value
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_RTCEx_MonotonicCounterGet(RTC_HandleTypeDef *hrtc, uint32_t *Counter, uint32_t Instance)
|
||||
HAL_StatusTypeDef HAL_RTCEx_MonotonicCounterGet(const RTC_HandleTypeDef *hrtc, uint32_t *Counter, uint32_t Instance)
|
||||
{
|
||||
UNUSED(hrtc);
|
||||
UNUSED(Instance);
|
||||
|
||||
Reference in New Issue
Block a user