/* * * This function initializes a XRtcPsu instance/driver. * * The initialization entails: * - Initialize all members of the XRtcPsu structure. * * @param InstancePtr is a pointer to the XRtcPsu instance. * @param ConfigPtr points to the XRtcPsu device configuration structure. * @param EffectiveAddr is the device base address in the virtual memory * address space. If the address translation is not used then the * physical address is passed. * Unexpected errors may occur if the address mapping is changed * after this function is invoked. * * @return XST_SUCCESS always. * * @note None. * ******************************************************************************/ s32 XRtcPsu_CfgInitialize(XRtcPsu *InstancePtr, XRtcPsu_Config *ConfigPtr, u32 EffectiveAddr) { s32 Status; Xil_AssertNonvoid(InstancePtr != NULL); Xil_AssertNonvoid(ConfigPtr != NULL); /* * Set some default values for instance data, don't indicate the device * is ready to use until everything has been initialized successfully. */ InstancePtr->IsReady = 0U; InstancePtr->RtcConfig.BaseAddr = EffectiveAddr; InstancePtr->RtcConfig.DeviceId = ConfigPtr->DeviceId; if(InstancePtr->OscillatorFreq == 0U) { InstancePtr->CalibrationValue = XRTC_CALIBRATION_VALUE; InstancePtr->OscillatorFreq = XRTC_TYPICAL_OSC_FREQ; } /* Set all handlers to stub values, let user configure this data later. */ InstancePtr->Handler = XRtcPsu_StubHandler; InstancePtr->IsPeriodicAlarm = 0U; /* Set the calibration value in calibration register. */ XRtcPsu_WriteReg(InstancePtr->RtcConfig.BaseAddr + XRTC_CALIB_WR_OFFSET, InstancePtr->CalibrationValue); /* Set the Oscillator crystal enable in control register. */ XRtcPsu_WriteReg(InstancePtr->RtcConfig.BaseAddr + XRTC_CTL_OFFSET, XRTCPSU_CRYSTAL_OSC_EN); /* Clear the Interrupt Status and Disable the interrupts. */ XRtcPsu_WriteReg(InstancePtr->RtcConfig.BaseAddr + XRTC_INT_STS_OFFSET, ((u32)XRTC_INT_STS_ALRM_MASK | (u32)XRTC_INT_STS_SECS_MASK)); XRtcPsu_WriteReg(InstancePtr->RtcConfig.BaseAddr + XRTC_INT_DIS_OFFSET, ((u32)XRTC_INT_DIS_ALRM_MASK | (u32)XRTC_INT_DIS_SECS_MASK)); /* Indicate the component is now ready to use. */ InstancePtr->IsReady = XIL_COMPONENT_IS_READY; Status = XST_SUCCESS; return Status; }
/** * * This function sets the interrupt mask. * * @param InstancePtr is a pointer to the XRtcPsu instance * @param Mask contains the interrupts to be enabled. * A '1' enables an interupt, and a '0' disables. * * @return None. * * @note None. * *****************************************************************************/ void XRtcPsu_SetInterruptMask(XRtcPsu *InstancePtr, u32 Mask) { /* * Clear the Status register to be sure of no pending interrupts. * Writing mask values to interrupt bits as it is a WTC register. */ XRtcPsu_WriteReg(InstancePtr->RtcConfig.BaseAddr + XRTC_INT_STS_OFFSET, ((u32)XRTC_INT_STS_ALRM_MASK | (u32)XRTC_INT_STS_SECS_MASK)); /* * XRTC_INT_MSK_RSTVAL contains the valid interrupts * for the RTC device. The AND operation on Mask makes sure one * of the valid bits are only set. */ /* Write the mask to the IER Register */ XRtcPsu_WriteReg(InstancePtr->RtcConfig.BaseAddr+XRTC_INT_EN_OFFSET, (Mask & (u32)XRTC_INT_MSK_RSTVAL)); }
/** * * This function clears the interrupt mask. * * @param InstancePtr is a pointer to the XRtcPsu instance * @param Mask contains the interrupts to be disabled. * A '1' enables an interrupt, and a '0' disables. * * @return None. * * @note None. * *****************************************************************************/ void XRtcPsu_ClearInterruptMask(XRtcPsu *InstancePtr, u32 Mask) { /* * XRTC_INT_MSK_RSTVAL contains the valid interrupts * for the RTC device. The AND operation on mask makes sure one * of the valid bits are only cleared. */ /* Write the Mask to the IDR register */ XRtcPsu_WriteReg(InstancePtr->RtcConfig.BaseAddr+XRTC_INT_DIS_OFFSET, (Mask & (u32)XRTC_INT_MSK_RSTVAL)); }
/** * * This function sets the alarm value of RTC device. * * @param InstancePtr is a pointer to the XRtcPsu instance * @param Alarm is the desired alarm time for RTC. * @param Periodic says whether the alarm need to set at periodic * Intervals or a one-time alarm. * * @return None. * * @note None. * *****************************************************************************/ void XRtcPsu_SetAlarm(XRtcPsu *InstancePtr, u32 Alarm, u32 Periodic) { Xil_AssertVoid(InstancePtr != NULL); Xil_AssertVoid(Alarm != 0U); Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); Xil_AssertVoid((Alarm - XRtcPsu_GetCurrentTime(InstancePtr)) > (u32)0); XRtcPsu_WriteReg(InstancePtr->RtcConfig.BaseAddr+XRTC_ALRM_OFFSET, Alarm); if(Periodic != 0U) { InstancePtr->IsPeriodicAlarm = 1U; InstancePtr->PeriodicAlarmTime = Alarm - XRtcPsu_GetCurrentTime(InstancePtr); } }
/** * * This function returns the alarm event status by reading * interrupt status register. * * @param InstancePtr is a pointer to the XRtcPsu instance. * * @return Returns 1 if the alarm event is generated.Else 0. * * @note This API is used in polled mode operation of RTC. * This also clears interrupt status alarm bit. * *****************************************************************************/ u32 XRtcPsu_IsAlarmEventGenerated(XRtcPsu *InstancePtr) { u32 Status; /* Loop the interrupt status register for Alarm Event */ if ((XRtcPsu_ReadReg(InstancePtr->RtcConfig.BaseAddr + XRTC_INT_STS_OFFSET) & (XRTC_INT_STS_ALRM_MASK)) == 0U) { Status = 0U; } else { /* Clear the interrupt status register */ XRtcPsu_WriteReg((InstancePtr)->RtcConfig.BaseAddr + XRTC_INT_STS_OFFSET, XRTC_INT_STS_ALRM_MASK); Status = 1U; } return Status; }
/** * * This function is the interrupt handler for the driver. * It must be connected to an interrupt system by the application such that it * can be called when an interrupt occurs. * * @param InstancePtr contains a pointer to the driver instance * * @return None. * * @note None. * ******************************************************************************/ void XRtcPsu_InterruptHandler(XRtcPsu *InstancePtr) { u32 IsrStatus; Xil_AssertVoid(InstancePtr != NULL); Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); /* * Read the interrupt ID register to determine which * interrupt is active. */ IsrStatus = ~(XRtcPsu_ReadReg(InstancePtr->RtcConfig.BaseAddr + XRTC_INT_MSK_OFFSET)); IsrStatus &= XRtcPsu_ReadReg(InstancePtr->RtcConfig.BaseAddr + XRTC_INT_STS_OFFSET); /* * Clear the interrupt status to allow future * interrupts before this generated interrupt is serviced. */ XRtcPsu_WriteReg(InstancePtr->RtcConfig.BaseAddr + XRTC_INT_STS_OFFSET, IsrStatus); /* Handle the generated interrupts appropriately. */ /* Alarm interrupt */ if((IsrStatus & XRTC_INT_STS_ALRM_MASK) != (u32)0) { if(InstancePtr->IsPeriodicAlarm != 0U) { XRtcPsu_SetAlarm(InstancePtr, (XRtcPsu_GetCurrentTime(InstancePtr)+InstancePtr->PeriodicAlarmTime),1U); } /* * Call the application handler to indicate that there is an * alarm interrupt. If the application cares about this alarm, * it will act accordingly through its own handler. */ InstancePtr->Handler(InstancePtr->CallBackRef, XRTCPSU_EVENT_ALARM_GEN); } /* Seconds interrupt */ if((IsrStatus & XRTC_INT_STS_SECS_MASK) != (u32)0) { /* Set the CurrTimeUpdated flag to 1 */ InstancePtr->CurrTimeUpdated = 1; if(InstancePtr->TimeUpdated == (u32)1) { /* Clear the TimeUpdated */ InstancePtr->TimeUpdated = (u32)0; } /* * Call the application handler to indicate that there is an * seconds interrupt. If the application cares about this seconds * interrupt, it will act accordingly through its own handler. */ InstancePtr->Handler(InstancePtr->CallBackRef, XRTCPSU_EVENT_SECS_GEN); } }