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 {
|
struct rtc_stm32_data {
|
||||||
/* Currently empty */
|
struct k_mutex lock;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int rtc_stm32_enter_initialization_mode(void)
|
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 device *const clk = DEVICE_DT_GET(STM32_CLOCK_CONTROL_NODE);
|
||||||
const struct rtc_stm32_config *cfg = dev->config;
|
const struct rtc_stm32_config *cfg = dev->config;
|
||||||
|
struct rtc_stm32_data *data = dev->data;
|
||||||
|
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
|
@ -143,6 +144,8 @@ static int rtc_stm32_init(const struct device *dev)
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
k_mutex_init(&data->lock);
|
||||||
|
|
||||||
/* Enable Backup access */
|
/* Enable Backup access */
|
||||||
z_stm32_hsem_lock(CFG_HW_RCC_SEMID, HSEM_LOCK_DEFAULT_RETRY);
|
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)
|
#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)
|
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;
|
uint32_t real_year = timeptr->tm_year + TM_YEAR_REF;
|
||||||
|
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
@ -195,11 +200,17 @@ static int rtc_stm32_set_time(const struct device *dev, const struct rtc_time *t
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err = k_mutex_lock(&data->lock, K_NO_WAIT);
|
||||||
|
if (err) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
LOG_INF("Setting clock");
|
LOG_INF("Setting clock");
|
||||||
LL_RTC_DisableWriteProtection(RTC);
|
LL_RTC_DisableWriteProtection(RTC);
|
||||||
|
|
||||||
err = rtc_stm32_enter_initialization_mode();
|
err = rtc_stm32_enter_initialization_mode();
|
||||||
if (err) {
|
if (err) {
|
||||||
|
k_mutex_unlock(&data->lock);
|
||||||
return err;
|
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);
|
LL_RTC_EnableWriteProtection(RTC);
|
||||||
|
|
||||||
|
k_mutex_unlock(&data->lock);
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int rtc_stm32_get_time(const struct device *dev, struct rtc_time *timeptr)
|
static int rtc_stm32_get_time(const struct device *dev, struct rtc_time *timeptr)
|
||||||
{
|
{
|
||||||
const struct rtc_stm32_config *cfg = dev->config;
|
const struct rtc_stm32_config *cfg = dev->config;
|
||||||
|
struct rtc_stm32_data *data = dev->data;
|
||||||
|
|
||||||
uint32_t rtc_date, rtc_time, rtc_subsecond;
|
uint32_t rtc_date, rtc_time, rtc_subsecond;
|
||||||
|
|
||||||
|
int err = k_mutex_lock(&data->lock, K_NO_WAIT);
|
||||||
|
|
||||||
|
if (err) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
do {
|
do {
|
||||||
/* read date, time and subseconds and relaunch if a day increment occurred
|
/* read date, time and subseconds and relaunch if a day increment occurred
|
||||||
* while doing so as it will result in an erroneous result otherwise
|
* 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_time != LL_RTC_TIME_Get(RTC));
|
||||||
} while (rtc_date != LL_RTC_DATE_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));
|
timeptr->tm_year = TM_TO_RTC_OFFSET + __LL_RTC_CONVERT_BCD2BIN(__LL_RTC_GET_YEAR(rtc_date));
|
||||||
/* tm_mon allowed values are 0-11 */
|
/* tm_mon allowed values are 0-11 */
|
||||||
timeptr->tm_mon = __LL_RTC_CONVERT_BCD2BIN(__LL_RTC_GET_MONTH(rtc_date)) - 1;
|
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);
|
ARG_UNUSED(dev);
|
||||||
|
|
||||||
uint32_t calp_enabled = LL_RTC_CAL_IsPulseInserted(RTC);
|
uint32_t calr = sys_read32(&RTC->CALR);
|
||||||
uint32_t calm = LL_RTC_CAL_GetMinus(RTC);
|
|
||||||
|
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);
|
int32_t nb_pulses = -((int32_t) calm);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue