реклама на сайте
подробности

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> Еще раз про powerdown, нужен совет
smk
сообщение Apr 16 2008, 07:32
Сообщение #1


Гуру
******

Группа: Свой
Сообщений: 2 246
Регистрация: 17-03-05
Из: Украина, Киев
Пользователь №: 3 446



С чего возник вопрос. Есть прибор, который с периодичностью 1 с просыпается и контролирует два параметра с помощью АЦП. Приборчик должен быть автономный и долгоиграющий. Чтобы знать, что приборчик работает и батарейки не сдохли предусмотрена индикация каждые 10 с, т.е. каждый десятый раз просыпания. Теперь сам вопрос.

На http://www.gaw.ru/html.cgi/txt/doc/micros/avr/arh128/4.htm прочитал:
Выход из режима сна происходит при возникновении разрешенного прерывания. В этом случае, помимо времени старта микроконтроллер приостанавливается на 4 машинных цикла, выполняет процедуру обработки прерывания и продолжает выполнять команды следующие за SLEEP. Содержимое файла регистров и статического ОЗУ остается неизменным после выхода из режима сна. Если во время действия режима сна возникает условие сброса, то микроконтроллер пробуждается и исполняет код программы по вектору сброса.

Можно ли использовать регистр ОЗУ под счетчик к-ва "пробуждений" и как это сделать программно? Желательно уходить в power-down, а просыпаться по WDT. Использую С, WinAVR. Спасибо!


--------------------
Живи днем так, чтобы ночью ты спал спокойно.
Go to the top of the page
 
+Quote Post
oran-be
сообщение Apr 17 2008, 14:55
Сообщение #2


Местный
***

Группа: Свой
Сообщений: 234
Регистрация: 30-03-07
Из: Одесса
Пользователь №: 26 621



Цитата(smk @ Apr 16 2008, 10:32) *
Можно ли использовать регистр ОЗУ под счетчик к-ва "пробуждений" и как это сделать программно? Желательно уходить в power-down, а просыпаться по WDT. Использую С, WinAVR. Спасибо!

Просыпание по WDT есть два варианта - использовать прерывание (мега48, 88, 168) или сброс по WDT.
Первый вариант типа возможен, но ввиду глюка прерывания от собаки работает не всегда. Если уходить в сброс, то необходимо счетчик засунуть в неинициализируемые данные. Если мне не изменяет память, в WinAVR необходимо объявить секцию с требуемыми атрибутами. (директива SECTION вроде). Тогда при сбросе эта секция перетираться не будет. Для инициализации первого включения после установки новых батарей необходимо будет добавить проверку на валидность значения этого счетчика - или CRC, или просто проинвертированное значение этого счетчика.
Go to the top of the page
 
+Quote Post
smk
сообщение Apr 17 2008, 16:35
Сообщение #3


Гуру
******

Группа: Свой
Сообщений: 2 246
Регистрация: 17-03-05
Из: Украина, Киев
Пользователь №: 3 446



Цитата
после установки новых батарей

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

Цитата
в WinAVR необходимо объявить секцию с требуемыми атрибутами.

Начинаю читать. Если кто-то знает как это делается - поделитесь опытом и (если можно) примером кода.

Я так понял речь об этгом?:
9.3.3 The .bss Section
Uninitialized global or static variables end up in the .bss section.

Как объявить такую переменную и как потом с ней обращаться?

Сообщение отредактировал smk - Apr 17 2008, 16:56


--------------------
Живи днем так, чтобы ночью ты спал спокойно.
Go to the top of the page
 
+Quote Post
Aleksandr Barano...
сообщение Apr 17 2008, 18:21
Сообщение #4


Частый гость
**

Группа: Участник
Сообщений: 169
Регистрация: 31-08-05
Из: New York
Пользователь №: 8 118



Цитата(smk @ Apr 17 2008, 12:35) *
В этой ситуации счет спокойно можно начинать с нуля. Суть в том, чтоб не утомлять пользователя частыми сигналами о работоспособности.
Начинаю читать. Если кто-то знает как это делается - поделитесь опытом и (если можно) примером кода.

Я так понял речь об этгом?:
9.3.3 The .bss Section
Uninitialized global or static variables end up in the .bss section.

Как объявить такую переменную и как потом с ней обращаться?




7.7.5 The .noinit Section
This sections is a part of the .bss section. What makes the
variables which are defined as such:
int foo __attribute__ ((section (".noinit")));


--------------------
ASB
Go to the top of the page
 
+Quote Post
smk
сообщение Apr 17 2008, 19:54
Сообщение #5


Гуру
******

Группа: Свой
Сообщений: 2 246
Регистрация: 17-03-05
Из: Украина, Киев
Пользователь №: 3 446



Если я правильно понял, то так будет работать:

int my_variable __attribute__ ((section (".noinit"))); //объявляем глобальной
.
.
.

if (my_variable==10)
{
//показываем, что прибор работает
my_variable=0;
}


Все правильно?


--------------------
Живи днем так, чтобы ночью ты спал спокойно.
Go to the top of the page
 
+Quote Post
Aleksandr Barano...
сообщение Apr 17 2008, 21:25
Сообщение #6


Частый гость
**

Группа: Участник
Сообщений: 169
Регистрация: 31-08-05
Из: New York
Пользователь №: 8 118



Цитата(smk @ Apr 17 2008, 15:54) *
Если я правильно понял, то так будет работать:

int my_variable __attribute__ ((section (".noinit"))); //объявляем глобальной
.
.
.

if (my_variable==10)
{
//показываем, что прибор работает
my_variable=0;
}
Все правильно?

Вот, что написано в мануале:

The .noinit Section
This sections is a part of the .bss section. What makes the .noinit section special is that variables which are defined as such:
int foo __attribute__ ((section (".noinit")));
will not be initialized to zero during startup as would normal .bss data.

Only uninitialized variables can be placed in the .noinit section. Thus, the following code will cause avr-gcc to issue an error:
int bar __attribute__ ((section (".noinit"))) = 0xaa;

It is possible to tell the linker explicitly where to place the .noinit section by adding -Wl,--section-start=.noinit=0x802000 to the avr-gcc command line at the linking stage. For example, suppose you wish to place the .noinit section at SRAM address 0x2000:

$ avr-gcc ... -Wl,--section-start=.noinit=0x802000 ...

Note:
Because of the Harvard architecture of the AVR devices, you must manually add 0x800000 to the address you pass to the linker as the start of the section. Otherwise, the linker thinks you want to put the .noinit section into the .text section instead of .data/.bss and will complain.


--------------------
ASB
Go to the top of the page
 
+Quote Post
Baser
сообщение Apr 17 2008, 21:49
Сообщение #7


Просто Che
*****

Группа: Свой
Сообщений: 1 567
Регистрация: 22-05-07
Из: ExUSSR
Пользователь №: 27 881



Цитата(smk @ Apr 17 2008, 19:35) *
Uninitialized global or static variables ...
Как объявить такую переменную и как потом с ней обращаться?

Как это в WinAVR не скажу, а в других компиляторах предельно просто. Есть расширение в виде ключевого слова.
В ИАР это: __no_init
В HiTech: persistent

Добавляется к любой переменной. Эта переменная попадает в секцию, которая не обнуляется после рестарта. Больше никаких отличий нет. Пример:

__no_init unsigned char Counter;

У меня в приборах с батарейным питанием половина переменных __no_init
Например регистры часов. Иначе любой случайный сброс - и время 00:00 smile.gif
Go to the top of the page
 
+Quote Post
smk
сообщение Apr 18 2008, 06:39
Сообщение #8


Гуру
******

Группа: Свой
Сообщений: 2 246
Регистрация: 17-03-05
Из: Украина, Киев
Пользователь №: 3 446



Цитата
Вот, что написано в мануале:

The .noinit Section
This sections is a part of the .bss section. What makes the .noinit section special is that variables which are defined as such:
int foo __attribute__ ((section (".noinit")));
will not be initialized to zero during startup as would normal .bss data.

Only uninitialized variables can be placed in the .noinit section. Thus, the following code will cause avr-gcc to issue an error:
int bar __attribute__ ((section (".noinit"))) = 0xaa;

It is possible to tell the linker explicitly where to place the .noinit section by adding -Wl,--section-start=.noinit=0x802000 to the avr-gcc command line at the linking stage. For example, suppose you wish to place the .noinit section at SRAM address 0x2000:

$ avr-gcc ... -Wl,--section-start=.noinit=0x802000 ...

Note:
Because of the Harvard architecture of the AVR devices, you must manually add 0x800000 to the address you pass to the linker as the start of the section. Otherwise, the linker thinks you want to put the .noinit section into the .text section instead of .data/.bss and will complain.


А как Вы сами это пользуете? Спасибо!

Вот это место не совсем понял:
Note: Because of the Harvard architecture of the AVR devices, you must manually add 0x800000 to the address you pass to the linker as the start of the section. Otherwise, the linker thinks you want to put the .noinit section into the .text section instead of .data/.bss and will complain.

Перевод: Примечание: Из-за Гарвардской архитектуры устройств AVR, вы должны вручную добавить 0x800000 по адресу, который вы передаете редактору связей как запуск секции. Иначе, редактор связей думает, что вы хотите поместить .noinit секцию в .text секцию вместо .data/.bss и будете жаловаться.

Сообщение отредактировал smk - Apr 18 2008, 07:10


--------------------
Живи днем так, чтобы ночью ты спал спокойно.
Go to the top of the page
 
+Quote Post
xelax
сообщение Apr 18 2008, 07:15
Сообщение #9


Местный
***

Группа: Свой
Сообщений: 370
Регистрация: 7-11-06
Пользователь №: 22 035



Цитата(smk @ Apr 17 2008, 23:54) *
Если я правильно понял, то так будет работать:

int my_variable __attribute__ ((section (".noinit"))); //объявляем глобальной

Все правильно?


Да правильно. Сам использую также:
uint8_t resetReason __attribute__ ((section (".noinit")));
Сохраняю там значение, если контроллер ресетнули программно. После ресета считываю то же значение, которое записал перед ресетом.
Спесиально эти секции в скрипте линкера не описываю, потому что WinAvr использует скрипты, где всё уже описанно.
После сборки проекта, можете сделать map карту проекта линкером и убедиться, что всё слинковалось куда надо.
wink.gif
Go to the top of the page
 
+Quote Post
smk
сообщение Apr 18 2008, 07:36
Сообщение #10


Гуру
******

Группа: Свой
Сообщений: 2 246
Регистрация: 17-03-05
Из: Украина, Киев
Пользователь №: 3 446



Цитата
Да правильно.

Спасибо! В студии работает как и было задумано. Интересно теперь как в железе будет...

И еще нужна консультация. Я правильно отправляю в power-down?

MCUCR=SLEEP_MODE_PWR_DOWN;
sleep_enable ();
sleep_mode ();

Спасибо!

Сообщение отредактировал smk - Apr 18 2008, 07:47


--------------------
Живи днем так, чтобы ночью ты спал спокойно.
Go to the top of the page
 
+Quote Post
xelax
сообщение Apr 18 2008, 08:41
Сообщение #11


Местный
***

Группа: Свой
Сообщений: 370
Регистрация: 7-11-06
Пользователь №: 22 035



Вы какую мегу юзаете?

В меге 1281, которую я использую есть регистр: SMCR – Sleep Mode Control Register. Вот его и пользую.
В даташите приведены кода всех энергосберегающих режимов.
В режим power down вхожу так:

Код
SMCR = (1 << SM1) | (1 << SE); // power-down
asm volatile ("sleep");


А MCUCR - MCU Control Register, что вы с помощью него хотите сделать?
Go to the top of the page
 
+Quote Post
smk
сообщение Apr 18 2008, 08:47
Сообщение #12


Гуру
******

Группа: Свой
Сообщений: 2 246
Регистрация: 17-03-05
Из: Украина, Киев
Пользователь №: 3 446



Цитата
Вы какую мегу юзаете?

tiny13

Цитата
А MCUCR - MCU Control Register, что вы с помощью него хотите сделать?

Там есть биты SE - sleep_enable; SM(1,0) - sleep_mode.

А Ваш пример явно мне интересен. Спасибо!


--------------------
Живи днем так, чтобы ночью ты спал спокойно.
Go to the top of the page
 
+Quote Post
xelax
сообщение Apr 18 2008, 08:58
Сообщение #13


Местный
***

Группа: Свой
Сообщений: 370
Регистрация: 7-11-06
Пользователь №: 22 035



Цитата(smk @ Apr 18 2008, 12:47) *
Там есть биты SE - sleep_enable; SM(1,0) - sleep_mode.


smile.gif Тогда наверное правильно. Надо смотреть что представляют из себя макросы и функции:
SLEEP_MODE_PWR_DOWN
sleep_enable ()
sleep_mode ()
Go to the top of the page
 
+Quote Post
smk
сообщение Apr 18 2008, 19:32
Сообщение #14


Гуру
******

Группа: Свой
Сообщений: 2 246
Регистрация: 17-03-05
Из: Украина, Киев
Пользователь №: 3 446



Всем спасибо, все заработало в железе. Может кому пригодится - выкладываю что получилось:

#include <avr/sleep.h>
#include <avr/wdt.h>

#define num_wdt_reset 10

char my_variable __attribute__ ((section (".noinit")));

int main (void)
{
my_variable++;

if (my_variable==num_wdt_reset)
{
my_variable=0;
}

wdt_enable(WDTO_1S);
set_sleep_mode (SLEEP_MODE_PWR_DOWN);
sleep_mode ();

while(1)
{
asm("nop");
}

return 0;
}

Сообщение отредактировал smk - Apr 18 2008, 20:12


--------------------
Живи днем так, чтобы ночью ты спал спокойно.
Go to the top of the page
 
+Quote Post
smk
сообщение May 18 2008, 15:37
Сообщение #15


Гуру
******

Группа: Свой
Сообщений: 2 246
Регистрация: 17-03-05
Из: Украина, Киев
Пользователь №: 3 446



Появился вот такой вопрос. При включении питания переменная my_variable будет иметь значение 0хFF, а при "просіпании" по сбросу от вочдог - последнее присвоенное значение? Цель вопроса - нужно надежно отличать старт при включении питания от старта по сбросу от вочдога. Кто как делает такое? Спасибо!


--------------------
Живи днем так, чтобы ночью ты спал спокойно.
Go to the top of the page
 
+Quote Post

2 страниц V   1 2 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 18th July 2025 - 06:29
Рейтинг@Mail.ru


Страница сгенерированна за 0.01493 секунд с 7
ELECTRONIX ©2004-2016