Миландр

Ключевым подразделением нашей компании
является Центр Проектирования интегральных микросхем
Текущее время: 2021-сен-22 02:10

Часовой пояс: UTC+03:00




Начать новую тему  Ответить на тему  [ 13 сообщений ] 
Автор Сообщение
 Заголовок сообщения: Сброс конфигурации RTC
СообщениеДобавлено: 2020-дек-21 01:04 
Не в сети

Зарегистрирован: 2020-дек-16 17:55
Сообщения: 9
Организация: частное лицо
Добрый день!
Сконфигурировал блок RTC для отображения времени на LCD-дисплее, работаю на отладочной плате для К1986BE92QI. Тактовым генератором является LSE, для того, чтобы регистры сохранялись при отключении основного питания.
Проблема: при отключении программатора JTAG (интерфейс JTAG-B) и включении платы наблюдаю, что значение счетчика сбросилось в 0 (отображается время "00:00", а на улице совсем не полночь). Попробовал при инициализации RTC запретить работу JTAG-B. Прошил МК и, как можно догадаться, второй раз прошить через JTAG уже не смог, пришлось возвращать старую прошивку через UART.
Вопрос: как исключить такое влияние JTAG на RTC?

Также есть еще пара интересных для меня проблем:
  1. Для того, чтобы повторно при перезапуске МК не происходила перенастройка RTC, в main добавил следующий код:
    ...
    if ((MDR_BKP->REG_0F & BKP_REG_0F_RTC_EN) == 0)
    {
    	rtc_init();
    }
    ...
    
    Но повторная инициализация все равно происходит, даже если флаг RTC_EN установлен.
  2. Необходимо ли задавать прерывания для счетчика часов? Сначала хотел сделать именно так, то есть сбрасывать счетчик по достижении 86400 секунд (то есть один день). Но сделал по другому, сейчас у меня считывается значение счетчика, от которого отрезается через операцию деления один день (или 86400 секунд), а счетчик продолжает инкрементироваться. По моим подсчетам его хватит на более чем 100 лет, если батарейка выдержит. Что я делаю не так?


Последний раз редактировалось bo4ka 2020-дек-30 11:24, всего редактировалось 1 раз.

Вернуться к началу
 Заголовок сообщения: Re: Сброс конфигурации RTC
СообщениеДобавлено: 2020-дек-21 10:24 
Не в сети

Зарегистрирован: 2014-июн-25 09:29
Сообщения: 146
Перемычка на плате рядом с батарейкой установлена?


Вернуться к началу
 Заголовок сообщения: Re: Сброс конфигурации RTC
СообщениеДобавлено: 2020-дек-21 15:52 
Не в сети

Зарегистрирован: 2020-дек-16 17:55
Сообщения: 9
Организация: частное лицо
andelie писал(а): *
Перемычка на плате рядом с батарейкой установлена?
да, если вы про XP6 (Vbat)


Вернуться к началу
 Заголовок сообщения: Re: Сброс конфигурации RTC из-за JTAG
СообщениеДобавлено: 2020-дек-23 11:22 
Не в сети

Зарегистрирован: 2018-мар-18 15:49
Сообщения: 263
Организация: StartMilandr.ru
bo4ka писал(а): *
Тактовым генератором является LSE, для того, чтобы регистры сохранялись при отключении основного питания.
LSE для блока RTC или на ядро тоже?
andelie писал(а): *
Но повторная инициализация все равно происходит, даже если флаг RTC_EN установлен.
Если флаг RTC_EN стоит, то приведенный код не вызовется. Если RTC_EN не стоит, тогда надо понять отчего об сбросился (вроде как не должен). Что значит, что "инициализация все-равно происходит"?

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


Вернуться к началу
 Заголовок сообщения: Re: Сброс конфигурации RTC из-за JTAG
СообщениеДобавлено: 2020-дек-24 11:36 
Не в сети

Зарегистрирован: 2020-дек-16 17:55
Сообщения: 9
Организация: частное лицо
StartMilandr писал(а): *
bo4ka писал(а): *
Тактовым генератором является LSE, для того, чтобы регистры сохранялись при отключении основного питания.
LSE для блока RTC или на ядро тоже?
andelie писал(а): *
Но повторная инициализация все равно происходит, даже если флаг RTC_EN установлен.
Если флаг RTC_EN стоит, то приведенный код не вызовется. Если RTC_EN не стоит, тогда надо понять отчего об сбросился (вроде как не должен). Что значит, что "инициализация все-равно происходит"?

Я бы проверил, что регистры BKP впринципе сохраняют свои значения при перезагрузке и что тактирование RTC точно идет от LSE.
Ядро наверное лучше тактировать чем-то другим, иначе все дико медленно получается.
Нет, для ядра у меня HSE 8 МГц подключается.
Наблюдал значения блока BKP при отладке, при входе в функцию main все значения регистров сохранились. НО тело if'а все равно выполнилось, функция rtc_init() отработала и сбросила счетчик RTC_CNT на то значение, которое я планировал задавать только один раз. То есть вот как я планировал: загрузил программу в МК с ненастроенным RTC, rtc_init() выполнила конфигурацию, а при следующем включении питания бранч if ((MDR_BKP->REG_0F & BKP_REG_0F_RTC_EN) == 0) уже не должен был отрабатываться.


Вернуться к началу
 Заголовок сообщения: Re: Сброс конфигурации RTC из-за JTAG
СообщениеДобавлено: 2020-дек-24 14:17 
Не в сети

Зарегистрирован: 2018-мар-18 15:49
Сообщения: 263
Организация: StartMilandr.ru
bo4ka писал(а): *
НО тело if'а все равно выполнилось,
Так ведь не бывает. :) Если бит стоит, то он стоит. Пройдитесь отладчиком по ассемблеру чтобы понять что не так.
И на всякий случай, проверьте включается ли тактирование блока BKP, и включается ли оно ДО проверки бита RTC_EN. Без тактирования регистры любого блока обычно читаются нулями.


Вернуться к началу
 Заголовок сообщения: Re: Сброс конфигурации RTC из-за JTAG
СообщениеДобавлено: 2020-дек-24 20:03 
Не в сети

Зарегистрирован: 2020-дек-16 17:55
Сообщения: 9
Организация: частное лицо
StartMilandr писал(а): *
bo4ka писал(а): *
НО тело if'а все равно выполнилось,
Так ведь не бывает. :) Если бит стоит, то он стоит. Пройдитесь отладчиком по ассемблеру чтобы понять что не так.
И на всякий случай, проверьте включается ли тактирование блока BKP, и включается ли оно ДО проверки бита RTC_EN. Без тактирования регистры любого блока обычно читаются нулями.
Всякое может быть :) Приложил скриншот дизасемблера, желтая строчка, которая подсвечивается, это как раз переход к функции rtc_init(). Что странно, в r0 загружается адрес регистра 0F, после проверки условия (перед входом в rtc_init()) значение регистра все таки меняется (видимо из за сдвига LSL) на 0xA8000000, но это некорректное выполнение.
Насчет тактирования не совсем понял. Что мне проверять, если я тактирую от LSE генератора, а он работает при выключенном питании. Когда запускаю отладку, то видно, что значения регистров BKP сохранились, а сам счетчик инкрементируется, если пройти пару шагов.


Вложения:
[ attachment ]
Asmarm.png [ 53.13 КБ | 1028 просмотров ]
Вернуться к началу
 Заголовок сообщения: Re: Сброс конфигурации RTC из-за JTAG
СообщениеДобавлено: 2020-дек-24 22:31 
Не в сети

Зарегистрирован: 2018-мар-18 15:49
Сообщения: 263
Организация: StartMilandr.ru
На счет тактирования, частоты две.
1 - LSE работая частота для BKP/RTC, на ней блок работает - "считает".
2 - HSE частота на которой работает ядро. Она же включается в регистре PER_CLOCK для блока BKP, чтобы ядро имело доступ к регистрам BKP. Если бит BKP[27] в PER_CLOCK не установить, то регистры блоков BKP-RTC будут читаться ядром нулями. Но у вас, по картинке видно, что REG_0F не нулевой, значит частота в PER_CLOCK подана.

Почему спросил про тактирование (ПРЕДПОЛОЖЕНИЕ):
Когда работает отладчик, то вероятно он грузит FLM внутрь озу, чтобы проверить что прошивка не изменилась и не требуется перепрошивка FLASH памяти. Память в данном случае вычитывается через FLM. Если прошивка изменилась при компиляции, то Keil прогружает обновленную, если галочка стоит в настройках. Этот FLM имеет функцию Init() которая включает тактирование BKP. Поэтому при загрузке под отладчиком бит BKP[27] в PER_CLOCK уже стоит когда вы попадаете на начало main. Далее вы видите что RTC сохранил настройки, флаг RTC_EN в REG_0F стоит. Поэтому исполнение НЕ ДОЛЖНО ЗАХОДИТЬ в rtc_init().

Но если запустить чип не в режиме отладки, то FLM не прогружается, BKP[27] в PER_CLOCK остается сброшенным после reset. При этом ядро читает регистр REG_0F нулевым и поэтому вызывается rtc_init().

Но судя по вашему изложению, у вас НЕ такое поведение. Значение в отладчике REG_0F не нулевое и RTC_EN стоит, следовательно выхода в rtc_init() быть не должно. Ассемблерную картинку я не могу оценить, т.к. IT - это "If-then-else", PL - это "Positive or Less" нуля. Если BKP_REG_0F_RTC_EN (0х10) << 27, то получится 0x8000_0000. Т.е. бит RTC_EN проверяется как знак, дальнейший код не доступен.

В чем косяк не представляю, но ядро не может вызвать функцию, если условие для этого не выполняется. Попробуйте выключить оптимизацию, если она есть, т.к. иногда при -O2 исполнение прыгает неисповедимым образом и понять что именно выполняется очень сложно. Может быть и тут что-нибудь подобное.
Больше идей нет :) Либо я совсем не так понял что происходит.


Вернуться к началу
 Заголовок сообщения: Re: Сброс конфигурации RTC из-за JTAG
СообщениеДобавлено: 2020-дек-25 10:01 
Не в сети

Зарегистрирован: 2018-мар-18 15:49
Сообщения: 263
Организация: StartMilandr.ru
О, а попробуйте посмотреть что в regValue читается:
volatile uint32_t regValue = MDR_BKP->REG_0F;
if ((regValue & BKP_REG_0F_RTC_EN) == 0)
{
	rtc_init();
}
Может быть действительно регистр неправильно читается на момент опроса. Если вдруг какой-нибудь баг пересинхронизации или первое чтение не проходит, частоты LSE и HSE сильно разные все-таки.


Вернуться к началу
 Заголовок сообщения: Re: Сброс конфигурации RTC из-за JTAG
СообщениеДобавлено: 2020-дек-30 11:24 
Не в сети

Зарегистрирован: 2020-дек-16 17:55
Сообщения: 9
Организация: частное лицо
StartMilandr писал(а): *
О, а попробуйте посмотреть что в regValue читается:
volatile uint32_t regValue = MDR_BKP->REG_0F;
if ((regValue & BKP_REG_0F_RTC_EN) == 0)
{
	rtc_init();
}
Может быть действительно регистр неправильно читается на момент опроса. Если вдруг какой-нибудь баг пересинхронизации или первое чтение не проходит, частоты LSE и HSE сильно разные все-таки.
В regValue записывалось корректное значение регистра 0F.
В общем то проблема решилась. Попробовал добавить включение тактирования BKP
RST_CLK_PCLKcmd(RST_CLK_PCLK_BKP, ENABLE)
и еще покрепче закрепил батарейку на плате :D но мне кажется из этого помогло последнее, потому что я еще раз перепрошил МК, закомментировав разрешение тактирования BKP, и часы работали даже при отключении JTAG.
Ну а на JTAG я думал, потому что часы ранее сбрасывались именно при его отключении от платы, но, видимо, он все таки никак не влияет на это.

А что скажете насчет второго вопроса про прерывания?


Вернуться к началу
 Заголовок сообщения: Re: Сброс конфигурации RTC
СообщениеДобавлено: 2020-дек-30 11:43 
Не в сети

Зарегистрирован: 2018-мар-18 15:49
Сообщения: 263
Организация: StartMilandr.ru
Если тактирование на любой периферийный блок не включено в PER_CLOCK, то запись в регистры этого блока не работает, а регистры блока читаются нулями!
Если что-то читаете/пишите в BKP, то предварительно включайте тактирование! Не полагайтесь на то, что тактирование останется включенным от FLM (как обсуждается в соседней ветке) / от прошлого старта или оно (тактирование) сохранилось еще каким-то чудесным образом. Тогда не будет неожиданных проблем!

Про прерывания я не понимаю, зачем они нужны. Но я не целиком представляю задачу.
Если часы тикают, то мне кажется не надо их вооще трогать. Т.к. операция на запись "собъет" ход часов.
Я бы рассмотрел вариант хранения предыдущего значения часов, что-то типа такого:
uint32_t lastDayTime = RTC_GetTime();
RTC_Start();

while (1) {
  if ((RTC_GetTime() - lastDayTime) > DAY_TICK_COUNT )
  {
     lastDayTime += DAY_TICK_COUNT;

     // SHOW DAY CHANGED
     ...
  }
}
Код условно, на вскидку. Только вот время 20-битное, и надо посмотреть как правильно обработать переполнение. Для 32-разрядного времени, такой код бы прокатил.

PS: Хотя, там вроде есть регистр ALRM и его удобно использовать для даты следующего прерывания. Увеличивайте ALRM на DAY_TICK_COUNT, и прерывание будет раз в день.


Вернуться к началу
 Заголовок сообщения: Re: Сброс конфигурации RTC
СообщениеДобавлено: 2020-дек-30 12:23 
Не в сети

Зарегистрирован: 2020-дек-16 17:55
Сообщения: 9
Организация: частное лицо
StartMilandr писал(а): *
Если тактирование на любой периферийный блок не включено в PER_CLOCK, то запись в регистры этого блока не работает, а регистры блока читаются нулями!
Если что-то читаете/пишите в BKP, то предварительно включайте тактирование! Не полагайтесь на то, что тактирование останется включенным от FLM (как обсуждается в соседней ветке) / от прошлого старта или оно (тактирование) сохранилось еще каким-то чудесным образом. Тогда не будет неожиданных проблем!
Понял, это действительно важно, теперь буду знать. Спасибо!
StartMilandr писал(а): *
Про прерывания я не понимаю, зачем они нужны. Но я не целиком представляю задачу.
Если часы тикают, то мне кажется не надо их вооще трогать. Т.к. операция на запись "собъет" ход часов.
Я бы рассмотрел вариант хранения предыдущего значения часов, что-то типа такого:
uint32_t lastDayTime = RTC_GetTime();
RTC_Start();

while (1) {
  if ((RTC_GetTime() - lastDayTime) > DAY_TICK_COUNT )
  {
     lastDayTime += DAY_TICK_COUNT;

     // SHOW DAY CHANGED
     ...
  }
}
Код условно, на вскидку. Только вот время 20-битное, и надо посмотреть как правильно обработать переполнение. Для 32-разрядного времени, такой код бы прокатил.

PS: Хотя, там вроде есть регистр ALRM и его удобно использовать для даты следующего прерывания. Увеличивайте ALRM на DAY_TICK_COUNT, и прерывание будет раз в день.
Да, вот как раз использование ALRM и имел в виду. В ALRM записать значение 86400 (секунд в сутках) и по его достижении в обработчике прерывания сбрасывать RTC_CNT и менять дату. Но ведь можно обойтись и без этого, если использовать начальное ("базовое") значение времени, которое будет записываться в RTC_CNT при первой инициализации RTC (+ еще сохранить где-нибудь начальную дату, например, в константе или в регистре аварийного сохранения или в памяти), и от него считать разницу между "базовым" и текущим временем и получать текущие дату и время. Вот и задумался, какой подход лучше использовать.
Но у меня задача простая, отобразить только время, без даты, и использую вариант без прерываний.
А регистр RTC_CNT 32-х разрядный ведь, 20-битными в BKP являются регистр счетчика предделителя (DIV) и регистр основания для счетчика предделителя (PRL).


Вернуться к началу
 Заголовок сообщения: Re: Сброс конфигурации RTC
СообщениеДобавлено: 2020-дек-30 12:46 
Не в сети

Зарегистрирован: 2018-мар-18 15:49
Сообщения: 263
Организация: StartMilandr.ru
Любой вариант хорош, если он работает! :)
Про 32-разрядные регистры спасибо что напомнили, лень было спецификацию качать смотреть, а по памяти уже не помню. Всплывало что-то про 20-ть..

Вариант с прерыванием еще хорош тем, что можно ядро в Sleep убрать через WFI/WFE (не помню что именно). Тогда по прерыванию от RTC ядро проснется, выведет новое время и снова в спячку. Теоретически... Но любой вариант надо проверять, а то бывает что только хуже получается. :)
bo4ka писал(а): *
В ALRM записать значение 86400 (секунд в сутках) и по его достижении в обработчике прерывания сбрасывать RTC_CNT и менять дату.
Только не сбрасывать CNT, а ALRM += 86400. Тогда CNT будет постоянно догонять ALRM, и при достижении генерировать прерывание.


Вернуться к началу
Показать сообщения за:  Поле сортировки  
Начать новую тему  Ответить на тему  [ 13 сообщений ] 

Часовой пояс: UTC+03:00


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и 4 гостя


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Перейти: 

cron
Создано на основе phpBB® Forum Software © phpBB Limited
Русская поддержка phpBB