Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: volatile указатель
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > Программирование
skyv
Добрый день.
Вопрос по использованию квалификатора volatile вроде обсуждался, но для себя хочу уточнить.
Имеем регистр аппаратуры, который объявлен в h файле как:
extern volatile unsigned int PORTB.
Как правильно определить аргумент функции в который передается адрес регистра аппаратуры:
- как указатель на переменную типа volatile - unsigned int * volatile ptr;
- как volatile указатель - volatile unsigned int *ptr;
- как volatile указатель на volatile переменную - volatile unsigned int * volatile ptr;
Спасибо.
msalov
Вы немного перепутали:
- указатель на переменную типа volatile - volatile unsigned int *ptr;
- volatile указатель - unsigned int * volatile ptr;

Что у вас изменяется вне программы? Указатель на регистр или значение регистра?

Полезное чтиво по чтению объявлений переменных -> http://www.unixwiz.net/techtips/reading-cdecl.html
skyv
Цитата(msalov @ Jan 16 2014, 12:44) *
Вы немного перепутали:
...


Да, согласен.
По Вашей ссылке посмотрю описание.
Я читал вот эту статью - volatile_for_chainiks.pdf.
И, если я правильно понял, автор советует всегда
использовать в качестве аргумента функции указатель на volatile переменную.
При этом сама переменная представляет собой регистр аппаратуры, который
объявлен как volatile.

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


Сергей Борщ
Цитата(skyv @ Jan 16 2014, 13:33) *
И, если я правильно понял, автор советует всегда
использовать в качестве аргумента функции указатель на volatile переменную.
"всегда" тут неуместно. Или вы не поняли, или мы вас. Если вы хотите передавать указатель на переменную, которая является volatile - вы должны параметр функции объявить как "указатель на volatile-переменную" (volatile int * param или int volatile * param, что одно и то же).
Если же вы хотите передавать указатель на обычную переменную - вы должны передавать указатель на обычную переменную. Не нужно считать компилятор дурнее себя - в подавляющем большинстве случаев оказыается наоборот.

Цитата(skyv @ Jan 16 2014, 13:33) *
Функция должна сделать некоторые действия над содержимым аппаратного
регистра (почитать, модифицировать, записать), может вернуть его значение.
В этом случае да. Но! Обычно в подобную функцию передается указатель на структуру, описывающую все регистры модуля периферии. И каждый из регитров описан как volatile. Вот в этом случае указатель на структуру не нужно объявлять как volatile - ибо сама структура не является volatile. Члены ее - да, а сама она - нет.
skyv
Цитата(Сергей Борщ @ Jan 16 2014, 14:58) *
"всегда" тут неуместно. ...


Применительно к моему исходному вопросу я однозначно указал, что рассматриваю
работу функции с регистром аппаратуры, который объявлен как volatile.
По крайней хотел рассмотреть только этот вариант.

По поводу применения указателей на структуру это, на мой взгляд, однозначно
зависит от того как объявлены регистры аппаратуры в h файле на CPU.
Так, к примеру, для различных ARMов регистры той или иной аппаратуры контроллера
упакованы в соответствующие структуры, а вот если посмотреть на объявления
для dsPIC, то там такого добра нет. В этом случае и приходится работать
не через указатели на структуры, а через указатели на регистры.



ViKo
По-моему, указатель определять volatile смысла нет. Это что получается - в программу передали указатель, который каким-то внешним воздействием вдруг может измениться? Страшно представить работу такой программы.
Другое дело volatile переменные, на которые указывает указатель. Аппаратная часть микроконтроллера, например.
Сергей Борщ
Цитата(skyv @ Jan 16 2014, 15:48) *
Применительно к моему исходному вопросу я однозначно указал, что рассматриваю
работу функции с регистром аппаратуры, который объявлен как volatile.

Вот ваше сообщение:
Цитата(skyv @ Jan 16 2014, 13:33) *
И, если я правильно понял, автор советует всегда использовать в качестве аргумента функции указатель на volatile переменную.
В конце стоит точка. Предложение (=мысль) закончилось.
А вот если объединить со следующим предложением:
Цитата(skyv @ Jan 16 2014, 13:33) *
При этом сама переменная представляет собой регистр аппаратуры, который объявлен как volatile.
то смысл пропадает совсем. Компилятор не позволит вам без грязных хаков (явных приведений типов) присвоить адрес volatile-переменной указателю на обычную (не-volatile) переменную. Что же тогда советует автор? Не нарушать правила языка? Так это очевидно, для этого не нужно статьи писать.
skyv
Цитата(Сергей Борщ @ Jan 16 2014, 18:57) *
...
Компилятор не позволит вам без грязных хаков (явных приведений типов) присвоить адрес volatile-переменной указателю на обычную (не-volatile) переменную. Что же тогда советует автор? Не нарушать правила языка? Так это очевидно, для этого не нужно статьи писать.


Вот именно в этом и вопрос, что же советует автор в своей статье в п. 2.1.4. Аргумент функции.

Сергей Борщ
Цитата(skyv @ Jan 16 2014, 17:27) *
Вот именно в этом и вопрос, что же советует автор в своей статье в п. 2.1.4. Аргумент функции.
Кто ж его знает...
Хотя... Проверил - Си допускает неявное приведение, но выдает предупреждение:
Код
volatile int A;
main()
{
    int * ptr = &A;
}

main.c: In function 'main':
main.c:6:17: warning: initialization discards 'volatile' qualifier from pointer target type [enabled by default]
     int * ptr = &A;

Плюсы в этом смысле более строги:
Код
main.cpp: In function 'int main()':
main.cpp:7:17: error: invalid conversion from 'volatile int*' to 'int*' [-fpermissive]
    int * ptr = &A;
Tarbal
volatile это инструкция для оптимизатора.

Один из вариантов:
Если переменная не изменяется посредством присваивания, допустим мы в нее что-то один раз записали, а потом только читаем. Можно сделать эквивалентную оптимизацию. Выиграть на чтении и записи в переменную, заменив все чтения подстановкой константы. И все будет прекрасно работать если это переменная в памяти. Однако если это регистр, то такая оптимизация недопустима. Слово volatile предотвращает оптимизацию для переменной, оставляя ее переменной.

Поскольку параметры функции не будут оптимизироваться подобным образом, то писать volatile для параметра не обязательно.
Rst7
QUOTE (ViKo @ Jan 16 2014, 16:00) *
По-моему, указатель определять volatile смысла нет. Это что получается - в программу передали указатель, который каким-то внешним воздействием вдруг может измениться? Страшно представить работу такой программы.


А что страшного-то? Например регистр, содержащий адрес пересылки DMA, и есть такой volatile-указатель.
Сергей Борщ
Цитата(Tarbal @ Jan 17 2014, 02:06) *
Поскольку параметры функции не будут оптимизироваться подобным образом, то писать volatile для параметра не обязательно.
Сам параметр (в этой дискуссии - указатель на переменную) меняться не будет, безусловно. И поэтому не "необязательно", а "не нужно совсем" - чтобы не плодить большие медленные программы. А вот та переменная, на которую указатель указывает (в этой дискуссии - регистр специального назначения, SFR), измениться может. И об этом компилятору надо сообщить. Поэтому такой параметр должен быть указателем на volatile-переменную.


Цитата(Rst7 @ Jan 17 2014, 12:09) *
Например регистр, содержащий адрес пересылки DMA, и есть такой volatile-указатель.
Но в Си такой регистр нельзя передать как параметр в функцию. Можно или передать его значение на момент вызова функции, либо указатель на него. При этом такой указатель будет все время указывать на регистр адреса пересылки DMA, т.е. не изменится. В Си с плюсами регистр можно передать в функцию в виде ссылки и вот тут да, это будет чистый и честный volatile-указатель. Однако в плюсах компилятор не даст потерять volatile при объявлении ссылки, то есть предмет споров пропадает.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.