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

 
 
 
Reply to this topicStart new topic
> volatile указатель
skyv
сообщение Jan 16 2014, 09:16
Сообщение #1


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

Группа: Участник
Сообщений: 181
Регистрация: 26-07-10
Пользователь №: 58 606



Добрый день.
Вопрос по использованию квалификатора volatile вроде обсуждался, но для себя хочу уточнить.
Имеем регистр аппаратуры, который объявлен в h файле как:
extern volatile unsigned int PORTB.
Как правильно определить аргумент функции в который передается адрес регистра аппаратуры:
- как указатель на переменную типа volatile - unsigned int * volatile ptr;
- как volatile указатель - volatile unsigned int *ptr;
- как volatile указатель на volatile переменную - volatile unsigned int * volatile ptr;
Спасибо.
Go to the top of the page
 
+Quote Post
msalov
сообщение Jan 16 2014, 09:44
Сообщение #2


Знающий
****

Группа: Свой
Сообщений: 526
Регистрация: 24-08-07
Из: Беларусь, Минск
Пользователь №: 30 045



Вы немного перепутали:
- указатель на переменную типа volatile - volatile unsigned int *ptr;
- volatile указатель - unsigned int * volatile ptr;

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

Полезное чтиво по чтению объявлений переменных -> http://www.unixwiz.net/techtips/reading-cdecl.html
Go to the top of the page
 
+Quote Post
skyv
сообщение Jan 16 2014, 11:33
Сообщение #3


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

Группа: Участник
Сообщений: 181
Регистрация: 26-07-10
Пользователь №: 58 606



Цитата(msalov @ Jan 16 2014, 12:44) *
Вы немного перепутали:
...


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

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


Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Jan 16 2014, 11:58
Сообщение #4


Гуру
******

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



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

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


--------------------
На любой вопрос даю любой ответ
"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
skyv
сообщение Jan 16 2014, 13:48
Сообщение #5


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

Группа: Участник
Сообщений: 181
Регистрация: 26-07-10
Пользователь №: 58 606



Цитата(Сергей Борщ @ Jan 16 2014, 14:58) *
"всегда" тут неуместно. ...


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

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



Go to the top of the page
 
+Quote Post
ViKo
сообщение Jan 16 2014, 14:00
Сообщение #6


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



По-моему, указатель определять volatile смысла нет. Это что получается - в программу передали указатель, который каким-то внешним воздействием вдруг может измениться? Страшно представить работу такой программы.
Другое дело volatile переменные, на которые указывает указатель. Аппаратная часть микроконтроллера, например.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Jan 16 2014, 14:57
Сообщение #7


Гуру
******

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



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

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


--------------------
На любой вопрос даю любой ответ
"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
skyv
сообщение Jan 16 2014, 15:27
Сообщение #8


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

Группа: Участник
Сообщений: 181
Регистрация: 26-07-10
Пользователь №: 58 606



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


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

Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Jan 16 2014, 18:05
Сообщение #9


Гуру
******

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



Цитата(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;


--------------------
На любой вопрос даю любой ответ
"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
Tarbal
сообщение Jan 17 2014, 00:06
Сообщение #10


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

Группа: Свой
Сообщений: 1 351
Регистрация: 21-05-10
Пользователь №: 57 439



volatile это инструкция для оптимизатора.

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

Поскольку параметры функции не будут оптимизироваться подобным образом, то писать volatile для параметра не обязательно.

Сообщение отредактировал Tarbal - Jan 17 2014, 00:13
Go to the top of the page
 
+Quote Post
Rst7
сообщение Jan 17 2014, 10:09
Сообщение #11


Йа моск ;)
******

Группа: Модераторы
Сообщений: 4 345
Регистрация: 7-07-05
Из: Kharkiv-city
Пользователь №: 6 610



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


А что страшного-то? Например регистр, содержащий адрес пересылки DMA, и есть такой volatile-указатель.


--------------------
"Практика выше (теоретического) познания, ибо она имеет не только достоинство всеобщности, но и непосредственной действительности." - В.И. Ленин
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Jan 17 2014, 10:45
Сообщение #12


Гуру
******

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



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


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


--------------------
На любой вопрос даю любой ответ
"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

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

 


RSS Текстовая версия Сейчас: 23rd July 2025 - 12:34
Рейтинг@Mail.ru


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