Перейти к содержанию
    

Добрый день,

 

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

 

есть ли в avr libc (поставляемой вместе с WinAvr) атомарная операция nop?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

static лишь ограничивает область видимости переменной текущим модулем(в котором она объявлена).

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

 

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

Это же относится и к функциям(функция в таком случае видна только внутри модуля).

явный static позволяет компилятору лучше оптимизировать код.

 

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

есть ли в avr libc (поставляемой вместе с WinAvr) атомарная операция nop?

 

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

 

#define nop() asm volatile("nop\n\t"::)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Еще немного про ОЗУ:

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

 

что означает спецификатор inline перед функцией? как это отразится МК, т.е. она будет какая то особая?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Еще немного про ОЗУ:

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

А информатики в школе не было? :biggrin:

ОЗУ - это то, что гаснет при выключении питания, а при включении может заполняться произвольными значениями.

В переменные, инициализированные при объявлении, значения заносятся процедурой startup, которая стартует перед main().

Остальные - ваша личная забота.

Объём маленький (по сравнению с флешью), потому что это дорогая, большая по физическим размерам и довольно прожорливая статическая память.

что означает спецификатор inline перед функцией? как это отразится МК, т.е. она будет какая то особая?

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

Это увеличивает быстродействие, а в случае совсем маленьких функций может даже экономить место.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

 

Уверены, что всегда размещаются в bss секции?

Есть предположение, что в примере переменная ляжет в секцию data.

void function(void)
{
  static uint8_t tempVariable = 0x55;
  ....
}

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Извиняюсь, что влезаю в чужой топик. Возникла непонятка со спецификатором 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), и соответственно при сравнении обнуляется. Если сделать глобальное объявление переменной, то проблема исчезает. Но почему так происходит, к сожалению понять так и не смог.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

Стеком поди затирается. Вообще, использование sin() и прочей плавучки внутри обработчика прерывания - это ну совсем нехорошо по целому ряду причин.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

И ещё у Вас UART буферизован?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Стеком поди затирается. Вообще, использование sin() и прочей плавучки внутри обработчика прерывания - это ну совсем нехорошо по целому ряду причин.

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

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

 

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

И ещё у Вас UART буферизован?

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Действительно стек на 32 байта, заполнен полностью.

:lol:

Да у вас один вызов функции может полстека съесть!

Что ж так жадничаете?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А можете рассказать про причины, или дать ссылку?

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

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

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...