Jump to content

    
Sign in to follow this  
Павел_Б

Вопрос по си

Recommended Posts

6 hours ago, Darth Vader said:

забить на предупреждение компилятора

Считаю, что это недопустимо. Я даже в IAR проектах добавляю опцию --warnings_are_errors, когда все предупреждения компилятор трактует как ошибки и не даёт возможность скомпилировать проект.

Share this post


Link to post
Share on other sites
4 часа назад, artemkad сказал:

аргумент как - "никто кроме функции её не поменяет".

А вот таких квалификаторов я не знаю. Это что-то новое.

Аргумент типа указатель на константу в объявлении (прототипе) функции значит, что "эта функция его не изменяет" (причем не аргумент-указатель, а объект, на который он указывает). Не более того. О константности и неизменности аргумента вне тела этой функции он не говорит ничего. Он может быть как константным, так и нет, и изменяться вне тела функции сколько угодно много раз.

 

Edited by Darth Vader

Share this post


Link to post
Share on other sites
2 часа назад, Darth Vader сказал:

А вот таких квалификаторов я не знаю. 

Это относится ко всем переменным не имеющим квалификатора volatile. Внутри функции они сами не меняются. Нет никакого прерывания DMA или другого потока который может внутри кода функции такую переменную изменить без её ведома.

ЗЫ. Кстати, че-то мне кажется что в CV (const char *p) это указатель на константу размещенную во флеше, а ему пытаются подсунуть указатель на переменную в оперативке... Куда этот указатель будет указывать - хз.

 

Share this post


Link to post
Share on other sites
7 часов назад, artemkad сказал:

а аргумент как - "никто кроме функции её не поменяет".

Вообще-то аргумент означает: "функция не меняет значение, адресуемое данным указателем". Почувствуйте разницу!

 

1 час назад, artemkad сказал:

Нет никакого прерывания DMA или другого потока который может внутри кода функции такую переменную изменить без её ведома.

volatile - это не только про переменные, меняемые в другим контексте. Вы его слишком узко трактуете.

Это про все переменные, порядок доступа к которым нельзя оптимизировать (изменить).

Например: Даже если регистры какой-то периферии используются только одной задачей, то их всё равно следует объявлять с volatile. Чтобы, например, если идёт работа с регистрами, чувствительными к чтению, оптимизатор не мог поменять порядок доступа к регистрам, нарушив таким образом алгоритм работы программы.

Share this post


Link to post
Share on other sites
1 час назад, jcxz сказал:

Например: Даже если регистры какой-то периферии используются только одной задачей, то их всё равно следует объявлять с volatile.

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

Share this post


Link to post
Share on other sites
14 минут назад, artemkad сказал:

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

Ещё раз: volatile не только потому что регистры где-то ещё или кем-то меняются.

А потому, что результат их чтения зависит от порядка этого чтения. Или порядка записи или и того и другого вместе - без разницы. Даже если эти регистры вообще не меняются.

Share this post


Link to post
Share on other sites
9 минут назад, jcxz сказал:

Ещё раз: volatile не только потому что регистры где-то ещё или кем-то меняются.

Только потому.

9 минут назад, jcxz сказал:

А потому, что результат их чтения зависит от порядка этого чтения.

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

Share this post


Link to post
Share on other sites
1 час назад, artemkad сказал:

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

Пример: FIFO передатчика в любой периферии (UART/SPI/etc.) - данные в FIFO записываем, а никакие регистры при этом не меняются. Значит, следуя вашей логике, можно убрать volatile из описания регистра FIFO?

Тогда оптимизатор вправе поменять порядок записи в регистры FIFO как считает нужным. И логика работы программы нарушится. :unknw:

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

Share this post


Link to post
Share on other sites
18 минут назад, jcxz сказал:

Пример: FIFO передатчика в любой периферии (UART/SPI/etc.) - данные в FIFO записываем, а никакие регистры при этом не меняются.

Как это - меняются регистры FIFO. Причем как они меняются компилятору создающему код ничего не известно. И их содержимое зависит не только от того, что туда записано, но и от внешних событий изымающих содержимое очереди и создателей этого самого FIFO и/или UART/SPI/etc. Естественно туда обязателен volatile именно из-за этого.

Share this post


Link to post
Share on other sites
1 час назад, artemkad сказал:

Как это - меняются регистры FIFO. Причем как они меняются компилятору создающему код ничего не известно.

В смысле - "неизвестно"? :wacko2: Они меняются в соответствии с записываемыми данными - что туда функция запишет, то там и будет. FIFO - это просто область ОЗУ, находящаяся в периферии.

1 час назад, artemkad сказал:

И их содержимое зависит не только от того, что туда записано, но и от внешних событий изымающих содержимое очереди и создателей этого самого FIFO и/или UART/SPI/etc.

Не обязательно. Передатчик может быть выключен во время записи. И ничто не "изымается". Но порядок записи всё равно важен.

1 час назад, artemkad сказал:

Естественно туда обязателен volatile именно из-за этого.

Так значит и для любой переменной вообще в ОЗУ нужен volatile? Если следовать вашей логике. Пишем в ОЗУ - значит её содержимое ведь меняется, значит нужен volatile, так что-ли?  :shok:

Share this post


Link to post
Share on other sites
31 минуту назад, jcxz сказал:

В смысле - "неизвестно"? 

Неизвестно компилятору. Например, ты сам-то сможешь однозначно сказать что получишь в ответ если прочитаешь только что записанный регистр FIFO?

31 минуту назад, jcxz сказал:

FIFO - это просто область ОЗУ,

 FIFO  это совсем не просто область ОЗУ, а область ОЗУ с кучей собственной логики работы которая, в частности, приводит к тому, что читаемые программой данные не совпадают  только что записанными. Т.е. с точки зрения компилятора это вообще не ОЗУ.

31 минуту назад, jcxz сказал:

Не обязательно. Передатчик может быть выключен во время записи. И ничто не "изымается".

Конечно обязательно. Даже если ничего не изымается чтение только что записанного в результате дает нечто совсем другое и зачастую даже из другого FIFO. Т.е. содержимое ячейки меняется самостоятельно по независимым от компилятора законам.

 

31 минуту назад, jcxz сказал:

Если следовать вашей логике. Пишем в ОЗУ - значит её содержимое ведь меняется, значит нужен , так что-ли? 

Это где-ж я такое написал? Пока содержимое ОЗУ зависит исключительно от логики программы - это обычные переменные. Такие переменные можно хоть в вечный цикл засунуть - они не поменяются пока контроллер не стукнуть чем ни будь тяжелым(например снятием питания). Как только они начинают зависеть от внешних факторов, событий или логики периферии контроллера о которых компилятор ничего не знает, эти уже volatile.

ЗЫ. Впрочем - volatile много не бывает ;)

Share this post


Link to post
Share on other sites
2 часа назад, artemkad сказал:

Неизвестно компилятору. Например, ты сам-то сможешь однозначно сказать что получишь в ответ если прочитаешь только что записанный регистр FIFO?

TX-FIFO обычно недоступно для чтения программой.

Цитата

 FIFO  это совсем не просто область ОЗУ, а область ОЗУ с кучей собственной логики работы которая, в частности, приводит к тому, что читаемые программой данные не совпадают  только что записанными. Т.е. с точки зрения компилятора это вообще не ОЗУ.

Если часть ОЗУ запретить на чтение или на запись через MPU, оно перестанет быть ОЗУ??? :wacko2:  Ведь в этом случае также как FIFO его нельзя будет прочитать/записать или результат будет отличаться.

Если в ОЗУ контроллера имеется аппаратный контроль чётности например (или другой способ контроля содержимого) - это тоже по вашей логике не ОЗУ получается?  :biggrin:

Странная у вас какая-то логика....  :unknw:

Цитата

Конечно обязательно. Даже если ничего не изымается чтение только что записанного в результате дает нечто совсем другое и зачастую даже из другого FIFO. Т.е. содержимое ячейки меняется самостоятельно по независимым от компилятора законам.

Не понимаю о каком чтении TX-FIFO говорите? В большинстве МК какие знаю - TX-FIFO недоступно для чтения. Вообще недоступно! Откройте мануал на любой МК с серьёзной периферией - просветитесь.

Цитата

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

Если исходить из этого "определения", то ОЗУ во многих ARM-ах вообще не существует. :biggrin: Так как у них есть MPU, есть MMU, есть контроллеры динамической памяти, есть ОЗУ с контролем чётности и от всего этого там зависит содержимое ОЗУ.

Share this post


Link to post
Share on other sites
15 minutes ago, jcxz said:

TX-FIFO обычно недоступно для чтения программой.

Наоборот, очень часто доступно. Встречал два поведения:

1) Всегда читаются нули

2) одни и те же адреса используются в качестве интерфейса TX FIFO (при записи в эти адреса) и RX FIFO (при чтении по этим же адресам)

 

15 minutes ago, jcxz said:

Если часть ОЗУ запретить на чтение или на запись через MPU, оно перестанет быть ОЗУ???

В большинстве случаев лучше считать, что ОЗУ вообще не существует. Есть процессор (с его системой команд, регистрами общего назначения, SFR, прерываниями)  и память. Просто память. Если нужно эту память как-то делить, это уже какая-то экзотика. Вы запретите запись через MPU? Нет, вы не запретите, запись исполнится процессором, но, в зависимости от настроек MPU (которая - периферия отображённая в память, т.е. с точки зрения процессора - опять же просто область памяти), результат этой записи может быть разным. И обработка таких событий опять же ограничивается обращениями в память и прерываниями.

Edited by one_eight_seven

Share this post


Link to post
Share on other sites
13 минут назад, one_eight_seven сказал:

Наоборот, очень часто доступно. Встречал два поведения:

1) Всегда читаются нули

2) одни и те же адреса используются в качестве интерфейса TX FIFO (при записи в эти адреса) и RX FIFO (при чтении по этим же адресам)

Это и есть - недоступно. Если его нельзя прочитать, значит - недоступно.

Share this post


Link to post
Share on other sites
Just now, jcxz said:

Это и есть - недоступно. Если его нельзя прочитать, значит - недоступно.

Нет. Это значит доступно и исполняется. Недоступно - это если оно BusFault или HardFault вызовет.

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this