НЕТАТИЧЕСКОЕ ЧИТАННЫЕ РЕГИСТРАЦИИ RTC

электрический
Пт. 09 февраля 2018 г. 5:12 утра
Я пытаюсь опередить вещи, пока жду, когда прибудет мое оборудование. RTC - очень важная вещь для меня, я бы предпочел не зависеть от внешних модулей RTC, поэтому я с нетерпением жду использования аппаратного обеспечения On Chip RTC. У меня есть некоторые идеи для реализации калибровки частоты программного обеспечения, которая предоставлена ​​на чипе, которые я представлю позже в отдельном потоке, когда все будет готово. С этой целью я копался в библиотеке Maple RTC и нашел то, что кажется тревожной проблемой. Верхние и нижние 16 бит текущего времени считываются отдельно, в то время как часы работают. Это означает, что могут быть времена, когда они не синхронизированы, и будут создавать неправильное время. Это потому, что значение счетчика может измениться между чтениями верхних и нижних 16 битов. Вот код: /** * @brief Returns the rtc's counter (i.e. time/date) value. * * This value is likely to be inaccurate if the counter is running * with a low prescaler. */ uint32 rtc_get_count() { uint32 h, l; rtc_clear_sync(); rtc_wait_sync(); rtc_wait_finished(); h = RTC->regs->CNTH & 0xffff; l = RTC->regs->CNTL & 0xffff; return (h << 16) | l; }

Стивестронг
Пт. 09 февраля 2018 г., 9:24
Можно было читать последовательно, пока последние два показания не станут идентичны.

электрический
Пт. 09 февраля 2018 г. 13:10
Да, это умнее. Я думаю, что лучше сделать это действие на уровне библиотеки, чем на уровне приложения. Поэтому я буду реализовать его и отправлю запрос на привлечение, когда смогу провести тестирование.

Racemaniac
Пт. 09 февраля 2018 г. 14:49
Было интересно, что STM не осознавал этого самостоятельно, очевидно, что они сделали:
RSF: Регистры синхронизированный флаг
Этот бит устанавливается аппаратным обеспечением каждый раз, когда обновляются регистры RTC_CNT и RTC_DIV
и очищен с помощью программного обеспечения. Перед какой -либо операцией чтения после сброса APB1 или часов APB1
Остановитесь, этот бит должен быть очищен с помощью программного обеспечения, а пользовательское приложение должно подождать, пока оно не будет установлено
Убедитесь, что регистры RTC_CNT, RTC_ALR или RTC_PRL синхронизированы.
0: регистры еще не синхронизированы.
1: регистры синхронизированы.

Таким образом, вы можете немного прояснить, что RTC будет устанавливать всякий раз, когда он обновляет свои регистры, и может использовать это, чтобы убедиться, что вы читаете только сразу после записи в эти регистры.

Не прочитал много дальше, но если можно прерывать от RTC после обновления регистров, это также может быть полезно для решения этого (если вы можете быстро справиться с прерыванием достаточно быстро)

*редактировать*
Мне также интересно, насколько хорошо будет работать предложенное повторное решение для чтения. Это работает отлично, если вы предполагаете, что запись атомна, но это гарантированно?

электрический
Пт. 09 февраля 2018 г., 18:37
Спасибо за Heads Up. Я также думал, что ST не позволит что -то подобному идти без решения. Похоже, гарантия приходит от проверки флага RSF, который в любом случае более чище, чем сравнивать регистры. Так что я посмотрю на это сегодня вечером. Код для меня новый, может быть, существующая функция уже проверяет ее где -нибудь.

Rogerclark
Пт. 09 февраля 2018 г., 20:34
Если вы улучшите существующий код, не могли бы вы опубликовать его или создать. PR на GitHub, чтобы мастер -код мог быть обновлен

электрический
Пт. 09 февраля 2018 г., 21:20
Если мое расследование заставит меня изменить ситуацию, я обязательно сделаю это. Здесь и как пиар. Мне нужно атомное чтение не только RTC_CNT, но и RTC_DIV, для процедуры калибровки RTC, которую я готовлю. Подробная информация об этом проекте последует, как только я успешно достигнут первой тестовой контрольной точки.

Rogerclark
Пт. 09 февраля 2018 г., 21:39
Спасибо

электрический
Сб 10 февраля 2018 г. 18:37
Хорошо, прошлой ночью я немного копал. На мой взгляд, мои первоначальные подозрения подтверждены. Мой взгляд Раздел 18.3.3 Чтение RTC Registers В руководстве пользователя состоит в том, что бит RSF указывает на синхронизацию между регистрами RTC и шиной APB1, не обязательно синхронизируя между различными регистрами RTC. Честно говоря, я рассчитал вероятность промахи, и что это, вероятно, произойдет один раз за 35 000 лет. :) Это может сделать проблему казаться довольно академической. Это также означает, что тестирование невозможно. Любая уверенность в этом должна быть от уверенности в алгоритме.

Однако, ради науки, я придумал два решения, которые я буду чувствовать себя уверенно. Оба являются реализациями двойного чтения и сравните. Я чувствую, что мне нужно некоторое руководство с этим, во -первых, это помогает мне познакомиться с механикой программного обеспечения, чтобы я мог перейти ко второму шагу, калибровка.

Одним из них является изменение класса, оставив функцию утилиты rtc_get_count () без изменений: time_t RTClock::getTime() { time_t t1, t2; do { t1 = rtc_get_count(); t2 = rtc_get_count(); } while (t1 != t2); return t2; } void RTClock::getTime(tm_t & tm_ptr) { time_t res = getTime(); breakTime(res, tm_ptr); }

Дэнниф
Сб 10 февраля 2018 г. 20:05
Это действительно выглядит так, как это ошибочно Вы правы. Код неверен.

Типичная стратегия - двойное чтение:
uint32_t msw, lsw; //most and least significant word do { msw = CNTH; //read the high word lsw = CNTL; //read the low word } while (msw ^ CNTH); //keep reading until msw:lsw are atomic return (msw << 16) | lsw;

электрический
Сб 10 февраля 2018 г., 21:02
Спасибо, Дэнни. Это тоже аккуратное сокращение! Я думаю, я также вижу, что не нужно также проверять низкое слово. Я обвиняю огромную метель, которая охватила мой город, и каким -то образом повлиял на мой мозг. Я отправил запрос на притяжение.