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

 
 
3 страниц V   1 2 3 >  
Reply to this topicStart new topic
> спецификатор static
John851
сообщение May 26 2010, 12:30
Сообщение #1


Участник
*

Группа: Участник
Сообщений: 50
Регистрация: 2-05-09
Пользователь №: 48 549



Добрый день,

в какой памяти AVR хранится переменная объявленная со спецификатором static?

есть ли в avr libc (поставляемой вместе с WinAvr) атомарная операция nop?
Go to the top of the page
 
+Quote Post
MrYuran
сообщение May 26 2010, 12:46
Сообщение #2


Беспросветный оптимист
******

Группа: Свой
Сообщений: 4 640
Регистрация: 26-12-07
Из: Н.Новгород
Пользователь №: 33 646



Цитата(John851 @ May 26 2010, 16:30) *
в какой памяти AVR хранится переменная объявленная со спецификатором static?

Если переменная, то в ОЗУ, где ж ей ещё быть


--------------------
Программирование делится на системное и бессистемное. ©Моё :)
— а для кого-то БГ — это Bill Gilbert =)
Go to the top of the page
 
+Quote Post
John851
сообщение May 26 2010, 12:54
Сообщение #3


Участник
*

Группа: Участник
Сообщений: 50
Регистрация: 2-05-09
Пользователь №: 48 549



абсолютно все переменные попадают в ОЗУ? или есть исключения?
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение May 26 2010, 13:11
Сообщение #4


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(John851 @ May 26 2010, 15:54) *
абсолютно все переменные попадают в ОЗУ? или есть исключения?
Если они объявлены с макросами PROGMEM (PSTR()), EEMEM - то во флеш и eeprom соответственно. Но доступ к ним должен осуществляться через соответствующие макросы. И static к этому отношения не имеет.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
sigmaN
сообщение May 26 2010, 15:01
Сообщение #5


I WANT TO BELIEVE
******

Группа: Свой
Сообщений: 2 617
Регистрация: 9-03-08
Пользователь №: 35 751



static лишь ограничивает область видимости переменной текущим модулем(в котором она объявлена).
Ещё static внутри функции - отдельная тема. Там область видимости уже не модуль, а функция, но значения переменной сохраняются между вызовами функции.

Вообще, для облегчения жизни компилятору, нужно всегда использовать static там, где оно действительно static.
Это же относится и к функциям(функция в таком случае видна только внутри модуля).
явный static позволяет компилятору лучше оптимизировать код.

Вообще static немного влияет на размещение переменных, но только в случае локальной переменной(внутри функции).
static переменная не размещается в стеке(как все локальные), а помещается в секцию .bss, ко всем остальным глобальным переменным(если мне не изменяет память).


--------------------
The truth is out there...
Go to the top of the page
 
+Quote Post
swisst
сообщение May 26 2010, 16:44
Сообщение #6


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

Группа: Свой
Сообщений: 163
Регистрация: 16-02-07
Из: Харьков
Пользователь №: 25 425



Цитата(John851 @ May 26 2010, 15:30) *
есть ли в avr libc (поставляемой вместе с WinAvr) атомарная операция nop?


добавлю свои пять копеек...

Код
#define nop() asm volatile("nop\n\t"::)
Go to the top of the page
 
+Quote Post
John851
сообщение May 27 2010, 05:30
Сообщение #7


Участник
*

Группа: Участник
Сообщений: 50
Регистрация: 2-05-09
Пользователь №: 48 549



Еще немного про ОЗУ:
А как происходит работа с ОЗУ? Переменные туда попадают при каждом старте МК или зашиваются при прошивке? Почему такой маленький объем этой памяти?

что означает спецификатор inline перед функцией? как это отразится МК, т.е. она будет какая то особая?
Go to the top of the page
 
+Quote Post
MrYuran
сообщение May 27 2010, 05:43
Сообщение #8


Беспросветный оптимист
******

Группа: Свой
Сообщений: 4 640
Регистрация: 26-12-07
Из: Н.Новгород
Пользователь №: 33 646



Цитата(John851 @ May 27 2010, 09:30) *
Еще немного про ОЗУ:
А как происходит работа с ОЗУ? Переменные туда попадают при каждом старте МК или зашиваются при прошивке? Почему такой маленький объем этой памяти?

А информатики в школе не было? biggrin.gif
ОЗУ - это то, что гаснет при выключении питания, а при включении может заполняться произвольными значениями.
В переменные, инициализированные при объявлении, значения заносятся процедурой startup, которая стартует перед main().
Остальные - ваша личная забота.
Объём маленький (по сравнению с флешью), потому что это дорогая, большая по физическим размерам и довольно прожорливая статическая память.
Цитата
что означает спецификатор inline перед функцией? как это отразится МК, т.е. она будет какая то особая?

Таким образом вы сообщаете компилятору, что хотели бы встроить тело функции в месте вызова, вместо того чтобы вызывать функцию через CALL.
Это увеличивает быстродействие, а в случае совсем маленьких функций может даже экономить место.


--------------------
Программирование делится на системное и бессистемное. ©Моё :)
— а для кого-то БГ — это Bill Gilbert =)
Go to the top of the page
 
+Quote Post
xelax
сообщение May 27 2010, 06:03
Сообщение #9


Местный
***

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



Цитата(sigmaN @ May 26 2010, 19:01) *
static переменная не размещается в стеке(как все локальные), а помещается в секцию .bss, ко всем остальным глобальным переменным(если мне не изменяет память).


Уверены, что всегда размещаются в bss секции?
Есть предположение, что в примере переменная ляжет в секцию data.
Код
void function(void)
{
  static uint8_t tempVariable = 0x55;
  ....
}
Go to the top of the page
 
+Quote Post
eracer
сообщение May 27 2010, 08:20
Сообщение #10


Участник
*

Группа: Участник
Сообщений: 17
Регистрация: 24-05-10
Пользователь №: 57 488



Извиняюсь, что влезаю в чужой топик. Возникла непонятка со спецификатором static, поэтому решил запостить сюда вопрос. Программа осуществляет ЦАП с помощью ШИМ. Запись в регистр сравнения осущетсвляется по прерыванию при переполнению счетчика.
Функция обработки прерывания выглядит следующим образом:
Код
__interrupt void T1_OVF_Handler()
{
    static unsigned int num = 0;
    temp = sin(2*pi*Fsin*num/Fpwm); //
    OCR1A = short(temp*TOP_PWM);
    num++;
    if (num >= Fpwm) num = 0;
    IntToChar(UART_out, 4, OCR1A);
    PutTextToUART(UART_out, 4);
}

При пошаговой отладке после вычисления синуса, значение num меняется на 22016 (причем Fpwm=7844), и соответственно при сравнении обнуляется. Если сделать глобальное объявление переменной, то проблема исчезает. Но почему так происходит, к сожалению понять так и не смог.
Go to the top of the page
 
+Quote Post
aaarrr
сообщение May 27 2010, 08:31
Сообщение #11


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(eracer @ May 27 2010, 12:20) *
При пошаговой отладке после вычисления синуса, значение num меняется на 22016 (причем Fpwm=7844), и соответственно при сравнении обнуляется. Если сделать глобальное объявление переменной, то проблема исчезает. Но почему так происходит, к сожалению понять так и не смог.

Стеком поди затирается. Вообще, использование sin() и прочей плавучки внутри обработчика прерывания - это ну совсем нехорошо по целому ряду причин.
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение May 27 2010, 09:30
Сообщение #12


неотягощённый злом
******

Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643



Попробуйте сделать табличку значений синуса с нужным шагом во флеши.
И ещё у Вас UART буферизован?


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
eracer
сообщение May 27 2010, 10:31
Сообщение #13


Участник
*

Группа: Участник
Сообщений: 17
Регистрация: 24-05-10
Пользователь №: 57 488



Цитата(aaarrr @ May 27 2010, 12:31) *
Стеком поди затирается. Вообще, использование sin() и прочей плавучки внутри обработчика прерывания - это ну совсем нехорошо по целому ряду причин.

Действительно стек на 32 байта, заполнен полностью. А можете рассказать про причины, или дать ссылку?
Знаю, что прерывания не должны "подвешивать" программу. Но в данном случае я проверял по количеству циклов, все вычисления уложаться до начала реверсивного счета.

Цитата
Попробуйте сделать табличку значений синуса с нужным шагом во флеши.
И ещё у Вас UART буферизован?

Проблема в том, что потребуется слишком много значений. Можно по идее ограничиться десятью и постепенно подгружать новые, но при этом нужно будет основную программу синхронизировать с прерыванием, чтобы в функцию обработки попадали только "нужные" значения. Это отдельная задача, и я еще над ней не задумывался. Та же проблема с UARTом, который тоже должен работать независимо.
Go to the top of the page
 
+Quote Post
MrYuran
сообщение May 27 2010, 10:37
Сообщение #14


Беспросветный оптимист
******

Группа: Свой
Сообщений: 4 640
Регистрация: 26-12-07
Из: Н.Новгород
Пользователь №: 33 646



Цитата(eracer @ May 27 2010, 14:31) *
Действительно стек на 32 байта, заполнен полностью.

lol.gif
Да у вас один вызов функции может полстека съесть!
Что ж так жадничаете?


--------------------
Программирование делится на системное и бессистемное. ©Моё :)
— а для кого-то БГ — это Bill Gilbert =)
Go to the top of the page
 
+Quote Post
aaarrr
сообщение May 27 2010, 10:37
Сообщение #15


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(eracer @ May 27 2010, 14:31) *
А можете рассказать про причины, или дать ссылку?

Причина в том, что работа с плавающей запятой по определению ресурсоемкая и медленная. Кроме того, данные функции не всегда являются реентерабельными (нужно справится в документации на конкретную библиотеку), что накладывает дополнительные ограничения на их использование в прерываниях.
Go to the top of the page
 
+Quote Post
eracer
сообщение May 27 2010, 11:15
Сообщение #16


Участник
*

Группа: Участник
Сообщений: 17
Регистрация: 24-05-10
Пользователь №: 57 488



Цитата(MrYuran @ May 27 2010, 14:37) *
lol.gif
Да у вас один вызов функции может полстека съесть!
Что ж так жадничаете?

Затруднил себя покопаться поглубже в настройках компилятора )) Мне казалось, что его размер выбирается автоматически
Go to the top of the page
 
+Quote Post
John851
сообщение May 27 2010, 12:27
Сообщение #17


Участник
*

Группа: Участник
Сообщений: 50
Регистрация: 2-05-09
Пользователь №: 48 549



хм, в чем разница объявления глобальной переменной в модуле?

int abc;

static int abc;

Разницы ведь никакой, переменная так и останется глобальной в пределах видимости модуля, дак зачем тогда еще и static прописывать?
Go to the top of the page
 
+Quote Post
MrYuran
сообщение May 27 2010, 12:35
Сообщение #18


Беспросветный оптимист
******

Группа: Свой
Сообщений: 4 640
Регистрация: 26-12-07
Из: Н.Новгород
Пользователь №: 33 646



Цитата(John851 @ May 27 2010, 16:27) *
Разницы ведь никакой, переменная так и останется глобальной в пределах видимости модуля, дак зачем тогда еще и static прописывать?

Вот именно, "в пределах видимости модуля".
То есть мы сообщаем компилятору, что за пределами данного модуля эта переменная не используется.
Что позволяет ему оптимизировать её в хвост и гриву.
То же самое относится и к функциям.
Вывод:
Если для вас разницы нет, пишите static везде, где можно.


--------------------
Программирование делится на системное и бессистемное. ©Моё :)
— а для кого-то БГ — это Bill Gilbert =)
Go to the top of the page
 
+Quote Post
aaarrr
сообщение May 27 2010, 12:36
Сообщение #19


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(John851 @ May 27 2010, 16:27) *
Разницы ведь никакой, переменная так и останется глобальной в пределах видимости модуля, дак зачем тогда еще и static прописывать?

Как это никакой? Во втором случае переменная будет видима только в пределах "своего" модуля.
Go to the top of the page
 
+Quote Post
mempfis_
сообщение May 27 2010, 14:35
Сообщение #20


Профессионал
*****

Группа: Свой
Сообщений: 1 001
Регистрация: 27-06-06
Пользователь №: 18 409



Цитата(John851 @ May 27 2010, 15:27) *
Разницы ведь никакой, переменная так и останется глобальной в пределах видимости модуля, дак зачем тогда еще и static прописывать?


Если при следующем вызове функции понадобится значение этой переменной (хотя я в своей практике программирования ещё такого не встречал) то объявляйте её static - компилятор выделит под неё память и будет использовать только выделенную область памяти при вызове этой функции и конкретно для этой переменной.

Без static компилятор выделит память в стеке и после использования переменной забудет о ней (при следующем вызове ф-ии эта переменная может быть положена в стек в любом доступном месте и её начальное значение может быть произвольным).

Вобщем IMHO static это ненужный расход оперативной памяти которая могла бы пойти на увеличение стека.
Go to the top of the page
 
+Quote Post
sigmaN
сообщение May 27 2010, 21:42
Сообщение #21


I WANT TO BELIEVE
******

Группа: Свой
Сообщений: 2 617
Регистрация: 9-03-08
Пользователь №: 35 751



Цитата
Вобщем IMHO static это ненужный расход оперативной памяти которая могла бы пойти на увеличение стека.
IMHO - ничего не понимаете вы в колбасных обрезках smile.gif


--------------------
The truth is out there...
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение May 27 2010, 23:24
Сообщение #22


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(mempfis_ @ May 27 2010, 17:35) *
Если при следующем вызове функции понадобится значение этой переменной
static для глобальных и локальных переменных имеет разное значение. Вопрос #17 был про глобальные переменные, а вы ответили про локальные.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
_Pasha
сообщение May 28 2010, 05:52
Сообщение #23


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Цитата(mempfis_ @ May 27 2010, 17:35) *
Если при следующем вызове функции понадобится значение этой переменной (хотя я в своей практике программирования ещё такого не встречал) то объявляйте её static


Код
void do_something(void)
{
static unsigned int ticks;
unsigned int tick_last;
//.................................
   tick_last = get_tick();
   if((tick_last - tick) > TIME_INTERVAL)
     {
        set_relay(1);
        tick = tick_last;
     }
}

Пример вызова ф-ции, включающей реле по наступлению момента времени TIME_INTERVAL с использованием некоей системы генерации системных тиков. А шо, не использовать же delay() в прерываниях!? biggrin.gif
Go to the top of the page
 
+Quote Post
MrYuran
сообщение May 28 2010, 06:25
Сообщение #24


Беспросветный оптимист
******

Группа: Свой
Сообщений: 4 640
Регистрация: 26-12-07
Из: Н.Новгород
Пользователь №: 33 646



Цитата(_Pasha @ May 28 2010, 09:52) *
А шо, не использовать же delay() в прерываниях!? biggrin.gif

А действительно, я как-то и не думал о таком применении.
Это ж можно макрос накатать типа
TIMER(interval,action)
и существенно обкультурить исходники


--------------------
Программирование делится на системное и бессистемное. ©Моё :)
— а для кого-то БГ — это Bill Gilbert =)
Go to the top of the page
 
+Quote Post
mempfis_
сообщение May 28 2010, 07:04
Сообщение #25


Профессионал
*****

Группа: Свой
Сообщений: 1 001
Регистрация: 27-06-06
Пользователь №: 18 409



Цитата(sigmaN @ May 28 2010, 00:42) *
IMHO - ничего не понимаете вы в колбасных обрезках smile.gif

Может быть всех тонкостей применения static не знаю - учился на электронщика а не программиста smile.gif
Но для глобальных переменных никогда его не применял smile.gif

Были конструкции такого типа (когдато подсказали сдесь на форуме)
Код
#define PutString(x) do{static __flash char  str[]=x; _putstring(str);}while(0);


Ну ещё в прерываниях по таймеру если нужно было с фиксированным периодом чтото выполнять
Код
void ISR_PIT();
{
  static unsigned int i=1000;

//вызов задачи раз в секунду
if(i>0) i--;
else
{
   i=1000;
   TaskON(5);
}
}



Цитата(Сергей Борщ @ May 28 2010, 02:24) *
static для глобальных и локальных переменных имеет разное значение. Вопрос #17 был про глобальные переменные, а вы ответили про локальные.


Вы правы - действительно мой ответ касался локальных переменных laughing.gif
В глобальных не приходилось применять - небыло необходимости объявлять переменные видимые только в одном модуле smile.gif

Сообщение отредактировал mempfis_ - May 28 2010, 07:04
Go to the top of the page
 
+Quote Post
sigmaN
сообщение May 28 2010, 07:44
Сообщение #26


I WANT TO BELIEVE
******

Группа: Свой
Сообщений: 2 617
Регистрация: 9-03-08
Пользователь №: 35 751



Цитата
В глобальных не приходилось применять - небыло необходимости объявлять переменные видимые только в одном модуле
Странно, а я напротив часто пару-тройку глобальных статиков имею.... Может быть не задумывались просто, что эта глобальная переменная только в этом файле нужна и можно немного ограничить её глобальность smile.gif

А может быть вместо нормально связывания - вяжете всё через глобальные переменные. А это как-то.... sad.gif


--------------------
The truth is out there...
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение May 28 2010, 09:29
Сообщение #27


неотягощённый злом
******

Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643



Цитата(mempfis_ @ May 28 2010, 11:04) *
В глобальных не приходилось применять - небыло необходимости объявлять переменные видимые только в одном модуле smile.gif
Какие Ваши годы:-) Рассматривайте механизм применения static для локалных объектов внутри одного модуля трансляции (файла) ещё и как дополнительный способ самодокументирования программы и всё встанен на свои места.

Также стоит понимать, что локальная статическая переменная внутри функции (более-менее существенного размера) не несёт накладных расходов на выделение стекового фрейма этой функции и если всё укладывается в регистры, то скорость выполнения этой функции возрастает а её размер уменьшается.
Но злоупотреблять этим не стоит...


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
John851
сообщение May 28 2010, 10:02
Сообщение #28


Участник
*

Группа: Участник
Сообщений: 50
Регистрация: 2-05-09
Пользователь №: 48 549



хм, а если я создам массив большой >1 Кб а памяти ОЗУ у меня всего 1Кб, тогда чего будет динамическая подгрузка данных из флэши?))
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение May 28 2010, 10:13
Сообщение #29


неотягощённый злом
******

Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643



Цитата(John851 @ May 28 2010, 14:02) *
хм, а если я создам массив большой >1 Кб а памяти ОЗУ у меня всего 1Кб, тогда чего будет динамическая подгрузка данных из флэши?))
Со статиком Вы обнаружите эту каку ещё на стадии билда проекта,
а без оного при первом его запуске в кристалле.


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
MrYuran
сообщение Jun 1 2010, 06:57
Сообщение #30


Беспросветный оптимист
******

Группа: Свой
Сообщений: 4 640
Регистрация: 26-12-07
Из: Н.Новгород
Пользователь №: 33 646



Цитата(MrYuran @ May 28 2010, 10:25) *
Это ж можно макрос накатать типа

Вот, накатал...
Попробовать, правда, пока не могу, некогда...
Код
/*********************************************************
*   Макрос для установки локального таймера
*   realtime - переменная системного времени
*   type - тип realtime
*   timer - временной интервал в тиках системного времени
*   action - действие по окончании интервала
*   continue - флаг "перезарядки" таймера
*********************************************************/
#define SET_TIMER(realtime, type, timer, action, continue)    \
do{ \
    static type timerVar = realtime + timer;    \
    if(timerVar>realtime){    \
        action;    \
        if(continue) timerVar = realtime + timer;   \
    }   \
}while(0)

Пример применения:
SET_TIMER(RealTime, unsigned int, 1000, DoSomething(), 1);
По идее, должен завести статическую переменную unsigned int под таймер,
отсчитать 1000 тиков, выполнить DoSomething() и перезапустить таймер

Вопрос на засыпку: локальную переменную создаст для do-while или для обёртывающей функции?


--------------------
Программирование делится на системное и бессистемное. ©Моё :)
— а для кого-то БГ — это Bill Gilbert =)
Go to the top of the page
 
+Quote Post
XVR
сообщение Jun 1 2010, 08:47
Сообщение #31


Гуру
******

Группа: Свой
Сообщений: 3 123
Регистрация: 7-04-07
Из: Химки
Пользователь №: 26 847



Цитата
Вопрос на засыпку: локальную переменную создаст для do-while или для обёртывающей функции?
Для do-while
Go to the top of the page
 
+Quote Post

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

 


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


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