Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: STM32, backup registers
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > ARM, 32bit
sonycman
Доброго времени суток!
Вот думаю использовать регистры бэкап домена.
Как бы прозрачнее это сделать, в идеале так, чтобы работа с ними не отличалась от работы с ячейками обычного ОЗУ?
Можно ли это?
baralgin
Из RM0008:
Backup data register x (BKP_DRx) (x = 1 ..42)
Address offset: 0x04 to 0x28, 0x40 to 0xBC

Первые 10 слов лежат подряд, остальные через интервал. Можно рассматривать как два массива с адресами (BKP_BASE + 0x0004) и (BKP_BASE + 0x0040) соответственно. Думаю около того:

Код
volatile uint32_t* BKPPartOne = (volatile uint32_t*)(BKP_BASE + 0x0004);
BKPPartOne[0] = 0x1234;
BKPPartOne[1] = 0x2345;
...
BKPPartOne[9] = 0xXXXX;

Не проверял, но по идее должно работать smile.gif .


Если нужно одним массивом, то можно завернуть это дело в класс с оператором [].
rezident
Стесняюсь спросить, а компиляторы про эту фичу не знают? А то вдруг они в курсе дела и используют ее по своему собственному разумению laughing.gif
sonycman
Спасибо за советы.
Реализация в виде дефайнов слишком простая и неудобная - всё надо делать ручками.

А вот обёртка в виде класса способна дать некое удобство и автоматизацию, но накладные расходы памяти будут совсем не кстати.
Да и если с переопределением dword, word и byte проблем не вижу, то как реализовать в классе работу со структурами я не знаю sad.gif

Наверное создам пока обычную структуру в памяти, и буду её время от времени записывать/считывать из энергонезависимого озу.

Насчёт компиляторов не в курсе.
Работаю в RealView, а он совсем не отличается широкой поддержкой всяких хитрых фич, в отличие от IAR sad.gif
baralgin
Цитата(sonycman @ Jun 9 2010, 15:34) *
А вот обёртка в виде класса способна дать некое удобство и автоматизацию, но накладные расходы памяти будут совсем не кстати.

Накладных расходов памяти не будет, только кода(и времени доступа). Сделать класс со статическими Set и Get для каждого члена "структуры", всё описать в хидере и после оптимизатора там будет очень компакный код. Собственно объект класса даже создавать не нужно, т.к. все методы будут статическими. Хотя никто не мешает так же завернуть это дело в static inline си-функции. Вопрос чисто эстетический smile.gif .
Цитата(sonycman @ Jun 9 2010, 15:34) *
Наверное создам пока обычную структуру в памяти, и буду её время от времени записывать/считывать из энергонезависимого озу.

По моему нормальный подход. Всё равно там этой backup-памяти кот наплакал(в мелких девайсах и вовсе 10 слов). Можно сделать универсальные:
Save(const void* inptr, size_t bytes) и Load(void* outptr, size_t bytes) и грузить туда любые конструкции.
adnega
помним, что слова BKP_DRx 16-битные и между ними есть 16-битные пустоты.
baralgin
adnega
так именно из-за этого то и весь сыр-бор разгорелся (ну и также из-за пробела между двумя "банками", который было бы желательно убрать).
adnega
Мне кажется, что "прозрачность" будет зависеть от того каким объемом данных оперируешь и как часто.

- Если до 16 бит, то определяем структуру и обращаемся к элементам структуры.

- Если больше, то завести удобную память - писать-читать из этой памяти. Перед чтением использовать load(byte *data), после записи save(byte *data).
load и save цена за "прозрачность".

Для хранения параметров устройства использовал load/save. И прозрачно, и логично.
sonycman
Ну, необходимость вызова функций Load\Save и "прозрачность" как то не совсем вяжутся.
adnega
Если под "прозрачностью" понимать непрерывность области данных, то это одно из решений решение.
Если нужен пословный доступ (по 16 бит), то можно написать необходимое число дефайнов.

Сам не пользовался, но кажется можно написать обработчик исключительной ситуации...

Например, обращаемся к несуществующему региону памяти (виртуальной батареечной памяти) как батареечной памяти. Обрабатываем исключение - если адреса из виртуальной батареечной памяти, то осуществляем доступ к реальной. Накладненько, но вроде "прозрачно". Так надо?

Будет работать?
sonycman
Нет, в моём понимании "прозрачность" - это когда работа со специфическими данными осуществляется точно так же, как и с обычными.
Пример:
Код
dword a = 100;
NON_VOLATILE b = 50;
if (b < a) b = a;

и т.д.

А ещё лучше было бы:
Код
NON_VOLATILE dword b;

NON_VOLATILE struct {
dword a;
word b;
byte c[5];
} timer;

Тут мы одновременно задаём тип данных и его размер.
Но это уже даже не Си, наверное...

Я не знаю, как этого добиться на Си или Си++ sad.gif
adnega
Добился-таки "прозрачности", но на lpc1768.

Проверял так:

BYTE *bat;

bat = (BYTE *)0x30000000; // несуществующая память
bat[0]=0x5A;

С позиций ядра bat[0]=num есть

STR rc, [ro]

rc - хранит число num, ro - хранит адрес назначения bat+0

Запись по несуществующему адресу вызывает исключение. В обработчике исключения подменяю ro на нужную ячейку памяти и выхожу (регистры R0-R3, R12 "проблемного участка" доступны через стек, остальные - напрямую). Команда STR выполняется еще раз, но уже с новым адресом.

У данного подхода есть ряд минусов:
- нужен контроллер с MPU. на STM32 не смог получить исключение в месте, где произвожу запись.
- поскольку rc и ro заранее не известны (впрочем команда тоже может быть не STR), то нужно анализировать инструкцию, которая привела к сбою.
- после выполнения инструкции параметры портятся, поэтому инструкцию лучше эмулировать.
Serj78
А у кого- нибудь получилось записать в эти регистры- хоть что- нибудь?
Я попробовал- нифига не выходит.
В лоб, по крайней мере:


BKP->DR2=2222;

a=BKP->DR2;

В отладчике сморю а=0... и BKP_DR2=0.... и переправить его руками из отладчика не получается??

Управляющие регистры BKP_CR и BKP_CSR обнулены..

Нифига не понимаю.. Может, что-то не так делаю?

Компилятор Keil 4.12
adnega
Цитата(Serj78 @ Dec 14 2010, 06:23) *
А у кого- нибудь получилось записать в эти регистры- хоть что- нибудь?
Я попробовал- нифига не выходит.
В лоб, по крайней мере:


BKP->DR2=2222;

a=BKP->DR2;

В отладчике сморю а=0... и BKP_DR2=0.... и переправить его руками из отладчика не получается??

Управляющие регистры BKP_CR и BKP_CSR обнулены..

Нифига не понимаю.. Может, что-то не так делаю?

Компилятор Keil 4.12


Необходимые питание и клоки включены?
zoddy
Цитата(Serj78 @ Dec 14 2010, 08:23) *
А у кого- нибудь получилось записать в эти регистры- хоть что- нибудь?


Я так и делаю
BKP->DRx = data;
data = BKP->DRx;
Все работает!


Скорее всего вы не разрешили запись в BKP. Что-то типа этого...

CODE

RCC_APB1PeriphClockCmd(RCC_APB1Periph_BKP | RCC_APB1Periph_PWR,ENABLE); // вкл тактирование нужной периферии
PWR_BackupAccessCmd(ENABLE);// разрешаем доступ к BKP
Serj78
А что включают ваши функции? (какие биты в каких регистрах)
RCC_APB1PeriphClockCmd(RCC_APB1Periph_BKP | RCC_APB1Periph_PWR,ENABLE); // вкл тактирование нужной периферии
PWR_BackupAccessCmd(ENABLE);// разрешаем доступ к BKP

Я включаю так:

RCC->APB1ENR|=(1<<27); // включили тактирование BKP
PWR->CR|=(1<<8); // разрешили запись в BKP

Включаю после включения всего тактирования и запуска PLL. Пробовал и до- не меняется ничего..

Но!! почему-то в отладчике я не вижу в этих регистрах установленных галочек.

А в PWR_CR бит PWR_CR_DBP вообще не выставляется из отладчика sad.gif пропадает сразу..
zoddy
Цитата(Serj78 @ Dec 14 2010, 11:55) *
А что включают ваши функции? (какие биты в каких регистрах)


Это функции из ST-шной библиотеки. Я особо над ними не заморачивался, выдернул из примера и вставил в свою прогу.

а вообще в Reference Manual написано

Цитата
After reset, access to the Backup registers and RTC is disabled and the Backup domain
(BKP) is protected against possible parasitic write access. To enable access to the Backup
registers and the RTC, proceed as follows:
● enable the power and backup interface clocks by setting the PWREN and BKPEN bits
in the RCC_APB1ENR register
● set the DBP bit the Power Control Register (PWR_CR) to enable access to the Backup
registers and RTC.


Соответственно у Вас закралась ошибка и скорее всего должно быть так
RCC->APB1ENR|=(1<<27)|(1<<28); // включили тактирование BKP и PWR
Serj78
Да, спасибо! узел контроля питания ( 28-й бит) включить забыл sm.gif !

zoddy
В общем, проверил на своей железяке вариант

RCC-> APB1ENR|=(1<<27)|(1<<28);
PWR-> CR |=(1<<8);

...работает


Цитата(Serj78 @ Dec 14 2010, 12:52) *
Да, спасибо! узел контроля питания ( 28-й бит) включить забыл sm.gif !


Вам тож спасибо, заодно свою программу чуток укоротил :-D... ато все руки не доходили!
AHTOXA
А если немножко удлиннить программу, написав вместо
Цитата(zoddy @ Dec 14 2010, 12:57) *
RCC-> APB1ENR|=(1<<27)|(1<<28);
PWR-> CR |=(1<<8);

что-то типа
Код
    RCC->APB1ENR |= RCC_APB1ENR_PWREN | RCC_APB1ENR_BKPEN;
    PWR->CR |= PWR_CR_DBP;
, то работать будет так же, а разбираться через месяц или через год - легчеsm.gif
Да и остальным читателям в форуме будет понятнее.
zoddy
Цитата(AHTOXA @ Dec 14 2010, 23:53) *
А если немножко удлиннить программу, написав вместо


Ну вообще-то... чуть выше по тексту, были приведены комментарии к выполняемым действиям... а уж... в каком виде оформлять битовые маски - это дело вкуса... я в данном случае написал так, как удобно для понимания автору, который задал вопрос :-)
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.