git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@7435 35acf78f-673a-0410-8e92-d51de3d6d3f4

This commit is contained in:
gdisirio 2014-10-30 14:24:38 +00:00
parent 0de9b5fb05
commit b665c20b66
3 changed files with 115 additions and 126 deletions

View File

@ -105,71 +105,6 @@ typedef struct {
/* Driver macros. */
/*===========================================================================*/
/**
* @brief Set current time.
*
* @param[in] rtcp pointer to RTC driver structure
* @param[in] timespec pointer to a @p RTCDateTime structure
*
* @iclass
*/
#define rtcSetTimeI(rtcp, timespec) \
rtc_lld_set_time(rtcp, timespec)
/**
* @brief Get current time.
*
* @param[in] rtcp pointer to RTC driver structure
* @param[out] timespec pointer to a @p RTCDateTime structure
*
* @iclass
*/
#define rtcGetTimeI(rtcp, timespec) \
rtc_lld_get_time(rtcp, timespec)
#if (RTC_ALARMS > 0) || defined(__DOXYGEN__)
/**
* @brief Set alarm time.
*
* @param[in] rtcp pointer to RTC driver structure
* @param[in] alarm alarm identifier
* @param[in] alarmspec pointer to a @p RTCAlarm structure or @p NULL
*
* @iclass
*/
#define rtcSetAlarmI(rtcp, alarm, alarmspec) \
rtc_lld_set_alarm(rtcp, alarm, alarmspec)
/**
* @brief Get current alarm.
* @note If an alarm has not been set then the returned alarm specification
* is not meaningful.
*
* @param[in] rtcp pointer to RTC driver structure
* @param[in] alarm alarm identifier
* @param[out] alarmspec pointer to a @p RTCAlarm structure
*
* @iclass
*/
#define rtcGetAlarmI(rtcp, alarm, alarmspec) \
rtc_lld_get_alarm(rtcp, alarm, alarmspec)
#endif /* RTC_ALARMS > 0 */
#if RTC_SUPPORTS_CALLBACKS || defined(__DOXYGEN__)
/**
* @brief Enables or disables RTC callbacks.
* @details This function enables or disables the callback, use a @p NULL
* pointer in order to disable it.
*
* @param[in] rtcp pointer to RTC driver structure
* @param[in] callback callback function pointer or @p NULL
*
* @iclass
*/
#define rtcSetCallbackI(rtcp, callback) \
rtc_lld_set_callback(rtcp, callback)
#endif /* RTC_SUPPORTS_CALLBACKS */
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/

View File

@ -67,19 +67,6 @@ RTCDriver RTCD1;
/* Driver local functions. */
/*===========================================================================*/
/**
* @brief Wait for synchronization of RTC registers with shadow registers.
* @details This function must be invoked before trying to access RTC
* registers.
*
* @notapi
*/
static void rtc_regs_sync(void) {
while ((RTCD1.rtc->ISR & RTC_ISR_RSF) == 0)
;
}
/**
* @brief Beginning of configuration procedure.
*
@ -221,7 +208,7 @@ static uint32_t rtc_encode_date(const RTCDateTime *timespec) {
/**
* @brief Enable access to registers.
*
* @api
* @notapi
*/
void rtc_lld_init(void) {
@ -232,92 +219,120 @@ void rtc_lld_init(void) {
RTCD1.rtc->WPR = 0xCA;
RTCD1.rtc->WPR = 0x53;
rtc_enter_init();
/* If calendar has not been initialized yet then proceed with the
initial setup.*/
if (!(RTCD1.rtc->ISR & RTC_ISR_INITS)) {
rtc_enter_init();
RTCD1.rtc->CR = 0;
RTCD1.rtc->ISR = 0;
RTCD1.rtc->PRER = STM32_RTC_PRER_BITS;
RTCD1.rtc->PRER = STM32_RTC_PRER_BITS;
rtc_exit_init();
}
else
RTCD1.rtc->ISR &= ~RTC_ISR_RSF;
rtc_exit_init();
}
/**
* @brief Set current time.
* @note Fractional part will be silently ignored. There is no possibility
* to set it on STM32 platform.
* @note The function can be called from any context.
*
* @param[in] rtcp pointer to RTC driver structure
* @param[in] timespec pointer to a @p RTCDateTime structure
*
* @api
* @notapi
*/
void rtc_lld_set_time(RTCDriver *rtcp, const RTCDateTime *timespec) {
uint32_t dr, tr;
syssts_t sts;
tr = rtc_encode_time(timespec);
dr = rtc_encode_date(timespec);
rtc_regs_sync();
/* Entering a reentrant critical zone.*/
sts = chSysGetStatusAndLockX();
/* Writing the registers.*/
rtc_enter_init();
rtcp->rtc->TR = tr;
rtcp->rtc->DR = dr;
rtc_exit_init();
/* Leaving a reentrant critical zone.*/
chSysRestoreStatusX(sts);
}
/**
* @brief Get current time.
* @note The function can be called from any context.
*
* @param[in] rtcp pointer to RTC driver structure
* @param[out] timespec pointer to a @p RTCDateTime structure
*
* @api
* @notapi
*/
void rtc_lld_get_time(RTCDriver *rtcp, RTCDateTime *timespec) {
uint32_t dr, tr, ssr;
uint32_t subs;
syssts_t sts;
rtc_regs_sync();
/* Entering a reentrant critical zone.*/
sts = chSysGetStatusAndLockX();
/* Synchronization with the RTC and reading the registers, note
DR must be read last.*/
while ((rtcp->rtc->ISR & RTC_ISR_RSF) == 0)
;
ssr = rtcp->rtc->SSR;
tr = rtcp->rtc->TR;
dr = rtcp->rtc->DR;
rtcp->rtc->ISR &= ~RTC_ISR_RSF;
/* Leaving a reentrant critical zone.*/
chSysRestoreStatusX(sts);
/* Decoding day time, this starts the atomic read sequence, see "Reading
the calendar" in the RTC documentation.*/
rtc_decode_time(rtcp->rtc->TR, timespec);
rtc_decode_time(tr, timespec);
/* If the RTC is capable of sub-second counting then the value is
normalized in milliseconds and added to the time.*/
#if STM32_RTC_HAS_SUBSECONDS
subs = (((rtcp->rtc->SSR << 16) / STM32_RTC_PRESS_VALUE) * 1000) >> 16;
subs = (((ssr << 16) / STM32_RTC_PRESS_VALUE) * 1000) >> 16;
#else
subs = 0;
#endif /* STM32_RTC_HAS_SUBSECONDS */
timespec->millisecond += subs;
/* Decoding date, this concludes the atomic read sequence.*/
rtc_decode_date(rtcp->rtc->DR, timespec);
rtc_decode_date(dr, timespec);
}
#if (RTC_ALARMS > 0) || defined(__DOXYGEN__)
/**
* @brief Set alarm time.
* @brief Set alarm time.
* @note Default value after BKP domain reset for both comparators is 0.
* @note Function does not performs any checks of alarm time validity.
* @note The function can be called from any context.
*
* @note Default value after BKP domain reset for both comparators is 0.
* @note Function does not performs any checks of alarm time validity.
* @param[in] rtcp pointer to RTC driver structure.
* @param[in] alarm alarm identifier. Can be 1 or 2.
* @param[in] alarmspec pointer to a @p RTCAlarm structure.
*
* @param[in] rtcp Pointer to RTC driver structure.
* @param[in] alarm Alarm identifier. Can be 1 or 2.
* @param[in] alarmspec Pointer to a @p RTCAlarm structure.
*
* @api
* @notapi
*/
void rtc_lld_set_alarm(RTCDriver *rtcp,
rtcalarm_t alarm,
const RTCAlarm *alarmspec) {
syssts_t sts;
/* Entering a reentrant critical zone.*/
sts = chSysGetStatusAndLockX();
if (alarm == 1) {
if (alarmspec != NULL) {
@ -349,20 +364,25 @@ void rtc_lld_set_alarm(RTCDriver *rtcp,
}
}
#endif /* RTC_ALARMS > 1 */
/* Leaving a reentrant critical zone.*/
chSysRestoreStatusX(sts);
}
/**
* @brief Get alarm time.
* @note The function can be called from any context.
*
* @param[in] rtcp pointer to RTC driver structure
* @param[in] alarm alarm identifier
* @param[out] alarmspec pointer to a @p RTCAlarm structure
*
* @api
* @notapi
*/
void rtc_lld_get_alarm(RTCDriver *rtcp,
rtcalarm_t alarm,
RTCAlarm *alarmspec) {
if (alarm == 1)
alarmspec->alrmr = rtcp->rtc->ALRMAR;
#if RTC_ALARMS > 1
@ -375,9 +395,9 @@ void rtc_lld_get_alarm(RTCDriver *rtcp,
#if STM32_RTC_HAS_PERIODIC_WAKEUPS || defined(__DOXYGEN__)
/**
* @brief Sets time of periodic wakeup.
*
* @note Default value after BKP domain reset is 0x0000FFFF
* @brief Sets time of periodic wakeup.
* @note Default value after BKP domain reset is 0x0000FFFF
* @note The function can be called from any context.
*
* @param[in] rtcp pointer to RTC driver structure
* @param[in] wakeupspec pointer to a @p RTCWakeup structure
@ -385,6 +405,10 @@ void rtc_lld_get_alarm(RTCDriver *rtcp,
* @api
*/
void rtcSTM32SetPeriodicWakeup(RTCDriver *rtcp, const RTCWakeup *wakeupspec) {
syssts_t sts;
/* Entering a reentrant critical zone.*/
sts = chSysGetStatusAndLockX();
if (wakeupspec != NULL) {
osalDbgCheck(wakeupspec->wutr != 0x30000);
@ -401,12 +425,15 @@ void rtcSTM32SetPeriodicWakeup(RTCDriver *rtcp, const RTCWakeup *wakeupspec) {
rtcp->rtc->CR &= ~RTC_CR_WUTIE;
rtcp->rtc->CR &= ~RTC_CR_WUTE;
}
/* Leaving a reentrant critical zone.*/
chSysRestoreStatusX(sts);
}
/**
* @brief Gets time of periodic wakeup.
*
* @note Default value after BKP domain reset is 0x0000FFFF
* @brief Gets time of periodic wakeup.
* @note Default value after BKP domain reset is 0x0000FFFF
* @note The function can be called from any context.
*
* @param[in] rtcp pointer to RTC driver structure
* @param[out] wakeupspec pointer to a @p RTCWakeup structure
@ -414,10 +441,17 @@ void rtcSTM32SetPeriodicWakeup(RTCDriver *rtcp, const RTCWakeup *wakeupspec) {
* @api
*/
void rtcSTM32GetPeriodicWakeup(RTCDriver *rtcp, RTCWakeup *wakeupspec) {
syssts_t sts;
/* Entering a reentrant critical zone.*/
sts = chSysGetStatusAndLockX();
wakeupspec->wutr = 0;
wakeupspec->wutr |= rtcp->rtc->WUTR;
wakeupspec->wutr |= (((uint32_t)rtcp->rtc->CR) & 0x7) << 16;
/* Leaving a reentrant critical zone.*/
chSysRestoreStatusX(sts);
}
#endif /* STM32_RTC_HAS_PERIODIC_WAKEUPS */

View File

@ -68,47 +68,61 @@ void rtcInit(void) {
/**
* @brief Set current time.
* @note This function can be called from any context but limitations
* could be imposed by the low level implementation. It is
* guaranteed that the function can be called from thread
* context.
* @note The function can be reentrant or not reentrant depending on
* the low level implementation.
*
* @param[in] rtcp pointer to RTC driver structure
* @param[in] timespec pointer to a @p RTCDateTime structure
*
* @api
* @special
*/
void rtcSetTime(RTCDriver *rtcp, const RTCDateTime *timespec) {
osalDbgCheck((rtcp != NULL) && (timespec != NULL));
osalSysLock();
rtcSetTimeI(rtcp, timespec);
osalSysUnlock();
rtc_lld_set_time(rtcp, timespec);
}
/**
* @brief Get current time.
* @note This function can be called from any context but limitations
* could be imposed by the low level implementation. It is
* guaranteed that the function can be called from thread
* context.
* @note The function can be reentrant or not reentrant depending on
* the low level implementation.
*
* @param[in] rtcp pointer to RTC driver structure
* @param[out] timespec pointer to a @p RTCDateTime structure
*
* @api
* @special
*/
void rtcGetTime(RTCDriver *rtcp, RTCDateTime *timespec) {
osalDbgCheck((rtcp != NULL) && (timespec != NULL));
osalSysLock();
rtcGetTimeI(rtcp, timespec);
osalSysUnlock();
rtc_lld_get_time(rtcp, timespec);
}
#if (RTC_ALARMS > 0) || defined(__DOXYGEN__)
/**
* @brief Set alarm time.
* @note This function can be called from any context but limitations
* could be imposed by the low level implementation. It is
* guaranteed that the function can be called from thread
* context.
* @note The function can be reentrant or not reentrant depending on
* the low level implementation.
*
* @param[in] rtcp pointer to RTC driver structure
* @param[in] alarm alarm identifier
* @param[in] alarmspec pointer to a @p RTCAlarm structure or @p NULL
*
* @api
* @special
*/
void rtcSetAlarm(RTCDriver *rtcp,
rtcalarm_t alarm,
@ -116,21 +130,25 @@ void rtcSetAlarm(RTCDriver *rtcp,
osalDbgCheck((rtcp != NULL) && (alarm < RTC_ALARMS));
osalSysLock();
rtcSetAlarmI(rtcp, alarm, alarmspec);
osalSysUnlock();
rtc_lld_set_alarm(rtcp, alarm, alarmspec);
}
/**
* @brief Get current alarm.
* @note If an alarm has not been set then the returned alarm specification
* is not meaningful.
* @note This function can be called from any context but limitations
* could be imposed by the low level implementation. It is
* guaranteed that the function can be called from thread
* context.
* @note The function can be reentrant or not reentrant depending on
* the low level implementation.
*
* @param[in] rtcp pointer to RTC driver structure
* @param[in] alarm alarm identifier
* @param[out] alarmspec pointer to a @p RTCAlarm structure
*
* @api
* @special
*/
void rtcGetAlarm(RTCDriver *rtcp,
rtcalarm_t alarm,
@ -138,9 +156,7 @@ void rtcGetAlarm(RTCDriver *rtcp,
osalDbgCheck((rtcp != NULL) && (alarm < RTC_ALARMS) && (alarmspec != NULL));
osalSysLock();
rtcGetAlarmI(rtcp, alarm, alarmspec);
osalSysUnlock();
rtc_lld_get_alarm(rtcp, alarm, alarmspec);
}
#endif /* RTC_ALARMS > 0 */
@ -149,19 +165,23 @@ void rtcGetAlarm(RTCDriver *rtcp,
* @brief Enables or disables RTC callbacks.
* @details This function enables or disables the callback, use a @p NULL
* pointer in order to disable it.
* @note This function can be called from any context but limitations
* could be imposed by the low level implementation. It is
* guaranteed that the function can be called from thread
* context.
* @note The function can be reentrant or not reentrant depending on
* the low level implementation.
*
* @param[in] rtcp pointer to RTC driver structure
* @param[in] callback callback function pointer or @p NULL
*
* @api
* @special
*/
void rtcSetCallback(RTCDriver *rtcp, rtccb_t callback) {
osalDbgCheck(rtcp != NULL);
osalSysLock();
rtcSetCallbackI(rtcp, callback);
osalSysUnlock();
rtc_lld_set_callback(rtcp, callback);
}
#endif /* RTC_SUPPORTS_CALLBACKS */