drivers: rtc: stm32: ensure thread safe operations
This adds mutex a lock in rtc_stm32_set_time and rtc_stm32_get_time to ensure consistent data reading. Also performs register reading in a single operation in rtc_stm32_get_calibration for the same reason. Signed-off-by: Johan Lafon <johan.lafon@syslinbit.com>
This commit is contained in:
parent
e46aff5902
commit
a8b7076099
1 changed files with 27 additions and 3 deletions
|
@ -67,7 +67,7 @@ struct rtc_stm32_config {
|
|||
};
|
||||
|
||||
struct rtc_stm32_data {
|
||||
/* Currently empty */
|
||||
struct k_mutex lock;
|
||||
};
|
||||
|
||||
static int rtc_stm32_enter_initialization_mode(void)
|
||||
|
@ -129,6 +129,7 @@ static int rtc_stm32_init(const struct device *dev)
|
|||
{
|
||||
const struct device *const clk = DEVICE_DT_GET(STM32_CLOCK_CONTROL_NODE);
|
||||
const struct rtc_stm32_config *cfg = dev->config;
|
||||
struct rtc_stm32_data *data = dev->data;
|
||||
|
||||
int err = 0;
|
||||
|
||||
|
@ -143,6 +144,8 @@ static int rtc_stm32_init(const struct device *dev)
|
|||
return -EIO;
|
||||
}
|
||||
|
||||
k_mutex_init(&data->lock);
|
||||
|
||||
/* Enable Backup access */
|
||||
z_stm32_hsem_lock(CFG_HW_RCC_SEMID, HSEM_LOCK_DEFAULT_RETRY);
|
||||
#if defined(PWR_CR_DBP) || defined(PWR_CR1_DBP) || defined(PWR_DBPCR_DBP) || defined(PWR_DBPR_DBP)
|
||||
|
@ -181,6 +184,8 @@ static const struct rtc_stm32_config rtc_config = {
|
|||
|
||||
static int rtc_stm32_set_time(const struct device *dev, const struct rtc_time *timeptr)
|
||||
{
|
||||
struct rtc_stm32_data *data = dev->data;
|
||||
|
||||
uint32_t real_year = timeptr->tm_year + TM_YEAR_REF;
|
||||
|
||||
int err = 0;
|
||||
|
@ -195,11 +200,17 @@ static int rtc_stm32_set_time(const struct device *dev, const struct rtc_time *t
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
err = k_mutex_lock(&data->lock, K_NO_WAIT);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
LOG_INF("Setting clock");
|
||||
LL_RTC_DisableWriteProtection(RTC);
|
||||
|
||||
err = rtc_stm32_enter_initialization_mode();
|
||||
if (err) {
|
||||
k_mutex_unlock(&data->lock);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -224,15 +235,24 @@ static int rtc_stm32_set_time(const struct device *dev, const struct rtc_time *t
|
|||
|
||||
LL_RTC_EnableWriteProtection(RTC);
|
||||
|
||||
k_mutex_unlock(&data->lock);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int rtc_stm32_get_time(const struct device *dev, struct rtc_time *timeptr)
|
||||
{
|
||||
const struct rtc_stm32_config *cfg = dev->config;
|
||||
struct rtc_stm32_data *data = dev->data;
|
||||
|
||||
uint32_t rtc_date, rtc_time, rtc_subsecond;
|
||||
|
||||
int err = k_mutex_lock(&data->lock, K_NO_WAIT);
|
||||
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
do {
|
||||
/* read date, time and subseconds and relaunch if a day increment occurred
|
||||
* while doing so as it will result in an erroneous result otherwise
|
||||
|
@ -247,6 +267,8 @@ static int rtc_stm32_get_time(const struct device *dev, struct rtc_time *timeptr
|
|||
} while (rtc_time != LL_RTC_TIME_Get(RTC));
|
||||
} while (rtc_date != LL_RTC_DATE_Get(RTC));
|
||||
|
||||
k_mutex_unlock(&data->lock);
|
||||
|
||||
timeptr->tm_year = TM_TO_RTC_OFFSET + __LL_RTC_CONVERT_BCD2BIN(__LL_RTC_GET_YEAR(rtc_date));
|
||||
/* tm_mon allowed values are 0-11 */
|
||||
timeptr->tm_mon = __LL_RTC_CONVERT_BCD2BIN(__LL_RTC_GET_MONTH(rtc_date)) - 1;
|
||||
|
@ -323,8 +345,10 @@ static int rtc_stm32_get_calibration(const struct device *dev, int32_t *calibrat
|
|||
{
|
||||
ARG_UNUSED(dev);
|
||||
|
||||
uint32_t calp_enabled = LL_RTC_CAL_IsPulseInserted(RTC);
|
||||
uint32_t calm = LL_RTC_CAL_GetMinus(RTC);
|
||||
uint32_t calr = sys_read32(&RTC->CALR);
|
||||
|
||||
bool calp_enabled = READ_BIT(calr, RTC_CALR_CALP);
|
||||
uint32_t calm = READ_BIT(calr, RTC_CALR_CALM);
|
||||
|
||||
int32_t nb_pulses = -((int32_t) calm);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue