STM32 новичку в ARM что к чему
- Сообщения: 2567
- Зарегистрирован: Вт май 01, 2018 19:44:47
И вы про атомарность. Это другой вопрос. Мухи отдельно, котлеты отдельно.
- Реклама
- Сообщения: 6457
- Зарегистрирован: Пт сен 13, 2013 13:11:31
[uquote="ARV",url="/forum/viewtopic.php?p=3895001#p3895001"]так никто и не ответил, каким образом может измениться поведение этой функции с/без volatile, если данные по указателю эта функция не использует?[/uquote]
А зачем отвечать на странные вопросы, которые к теме в данном случае отношения не имеют? С тем же успехом вы бы могли требовать ответа на вопрос, как влияет частое употребление модификатора volatile на состав кишечных газов.
А зачем отвечать на странные вопросы, которые к теме в данном случае отношения не имеют? С тем же успехом вы бы могли требовать ответа на вопрос, как влияет частое употребление модификатора volatile на состав кишечных газов.
Напомню, что:
[uquote="a5021",url="/forum/viewtopic.php?p=3894133#p3894133"]Объясните, кто знает, плс, почему в неблокирующую функцию
указатель на буфер pData передается без модификатора volatile ? Чет это на какой-то зашквар смахивает.[/uquote]
Вы сами начали задавать странные вопросы. Априори полагая, что volatile - правильно, а без него - какие-то выдуманные глюки и страдания будут.
[uquote="a5021",url="/forum/viewtopic.php?p=3894133#p3894133"]Объясните, кто знает, плс, почему в неблокирующую функцию
Код: Выделить всё
HAL_StatusTypeDef HAL_SPI_Receive_DMA(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size)Вы сами начали задавать странные вопросы. Априори полагая, что volatile - правильно, а без него - какие-то выдуманные глюки и страдания будут.
- Сообщения: 2516
- Зарегистрирован: Пт июл 12, 2019 22:52:01
[uquote="WiseLord",url="/forum/viewtopic.php?p=3895275#p3895275"]Априори полагая, что volatile - правильно, а без него - какие-то выдуманные глюки и страдания будут.[/uquote]
Чтобы не было глюков и страданий, нужно просто перестать всякими "халами" пользоваться!
Чтобы не было глюков и страданий, нужно просто перестать всякими "халами" пользоваться!
Linux rules! Windows must die. Здравомыслящий человек добровольно будет пользоваться мастдаем лишь в двух случаях: под дулом автомата или под влиянием анального зонда.
Я на гитхабе, в ЖЖ
Я на гитхабе, в ЖЖ
- Сообщения: 6457
- Зарегистрирован: Пт сен 13, 2013 13:11:31
[uquote="WiseLord",url="/forum/viewtopic.php?p=3895275#p3895275"]Вы сами начали задавать странные вопросы. Априори полагая, что volatile - правильно, а без него - какие-то выдуманные глюки и страдания будут.[/uquote]
Когда функция молча принимает неверные параметры, но ругается на верные, это выдуманные страдания? Ну поздравьте себя.
[uquote="Eddy_Em",url="/forum/viewtopic.php?p=3895318#p3895318"]Чтобы не было глюков и страданий, нужно просто перестать всякими "халами" пользоваться![/uquote]
Судя по тому, какое количество фанатов хала понабежало, говорить такие вещи здесь -- пустое дело.
Когда функция молча принимает неверные параметры, но ругается на верные, это выдуманные страдания? Ну поздравьте себя.
[uquote="Eddy_Em",url="/forum/viewtopic.php?p=3895318#p3895318"]Чтобы не было глюков и страданий, нужно просто перестать всякими "халами" пользоваться![/uquote]
Судя по тому, какое количество фанатов хала понабежало, говорить такие вещи здесь -- пустое дело.
- Реклама
Нет, это просто Вы передаёте ей неверные параметры.a5021 писал(а):Когда функция молча принимает неверные параметры, но ругается на верные, это выдуманные страдания?
Добавлено after 1 minute 32 seconds:
А вот это - двумя руками поддерживаю. И автоматически причин к недовольству не будет.Eddy_Em писал(а):Чтобы не было глюков и страданий, нужно просто перестать всякими "халами" пользоваться!
- Сообщения: 6457
- Зарегистрирован: Пт сен 13, 2013 13:11:31
[uquote="WiseLord",url="/forum/viewtopic.php?p=3895325#p3895325"]Нет, это просто Вы передаёте ей неверные параметры.[/uquote]
Эти "неверные" ?

Просите Мурика, быть может он сжалится и вышлет вам букварь про волатайл повторно.
Эти "неверные" ?
Просите Мурика, быть может он сжалится и вышлет вам букварь про волатайл повторно.
Да, неверные. Функция хочет указатель на uint8_t, а её передаётся массив volatile uint8_t. Вы используете функцию не по назначению.
Это как если бы в функцию, принимающую строку я захотел бы передать int. Ну вот просто потому, что считаю - что int - это good, а строки - это bad. Правда, тут warning-ом бы не обошлось - но это и бзик побольше.
P.S. По третьему примеру явно видно, что проблема не в функции, а в самом good_buffer:

Это как если бы в функцию, принимающую строку я захотел бы передать int. Ну вот просто потому, что считаю - что int - это good, а строки - это bad. Правда, тут warning-ом бы не обошлось - но это и бзик побольше.
P.S. По третьему примеру явно видно, что проблема не в функции, а в самом good_buffer:
- Сообщения: 6457
- Зарегистрирован: Пт сен 13, 2013 13:11:31
[uquote="WiseLord",url="/forum/viewtopic.php?p=3895340#p3895340"]Да, неверные. Функция хочет указатель на uint8_t, а её передаётся массив volatile uint8_t. Вы используете функцию не по назначению.[/uquote]
Для вас, поди, новость еще и то, что под DMA-трансфер переменная должна быть объявлена, как volatile ?
Для вас, поди, новость еще и то, что под DMA-трансфер переменная должна быть объявлена, как volatile ?
Не должна.
P.S. Чтобы это звучало голословно, простой пример: периодически считываем результат преобразования АЦП микроконтроллера в буфер из, скажем, 4 элементов, постоянно и циклически. Цель иметь усредненённое значение последних 4 измерений, чтобы уменьшить шум преобразования. Тут совершенно не нужен volatile.
P.S. Чтобы это звучало голословно, простой пример: периодически считываем результат преобразования АЦП микроконтроллера в буфер из, скажем, 4 элементов, постоянно и циклически. Цель иметь усредненённое значение последних 4 измерений, чтобы уменьшить шум преобразования. Тут совершенно не нужен volatile.
- Сообщения: 6457
- Зарегистрирован: Пт сен 13, 2013 13:11:31
[uquote="WiseLord",url="/forum/viewtopic.php?p=3895346#p3895346"]Не должна.
P.S. Чтобы это звучало голословно, простой пример: периодически считываем результат преобразования АЦП микроконтроллера в буфер из, скажем, 4 элементов, постоянно и циклически. Цель иметь усредненённое значение последних 4 измерений, чтобы уменьшить шум преобразования. Тут совершенно не нужен volatile.[/uquote]
Вот эта ваша "не должна", она работает только для вашего примера или для любых случаев?
P.S. Чтобы это звучало голословно, простой пример: периодически считываем результат преобразования АЦП микроконтроллера в буфер из, скажем, 4 элементов, постоянно и циклически. Цель иметь усредненённое значение последних 4 измерений, чтобы уменьшить шум преобразования. Тут совершенно не нужен volatile.[/uquote]
Вот эта ваша "не должна", она работает только для вашего примера или для любых случаев?
[uquote="WiseLord",url="/forum/viewtopic.php?p=3895346#p3895346"]Тут совершенно не нужен volatile.[/uquote]
Прошу прощения, но с чего вы решили, что компилятор не закеширует значение всех четырех измерений в регистрах и Вы в итоге не будете получать один и тот же результат, вообще не зависящий от результатов преобразования АЦП?
Прошу прощения, но с чего вы решили, что компилятор не закеширует значение всех четырех измерений в регистрах и Вы в итоге не будете получать один и тот же результат, вообще не зависящий от результатов преобразования АЦП?
Одного опровергающего примера уже достаточно, чтобы общее утверждение "DMA буфер должен быть всегда volatile" стало ложным.a5021 писал(а):Вот эта ваша "не должна", она работает только для вашего примера или для любых случаев?
Добавлено after 3 minutes 26 seconds:
Хотя бы с того, что в функции они мне нужны только один раз - прочитать и усреднить. При выходе эти регистры из стека уйдут, при повторном вызове фунций, снова попадут в стек и будут заполнены заново.ПростоНуб писал(а):с чего вы решили, что компилятор не закеширует значение всех четырех измерений в регистрах
- Сообщения: 6457
- Зарегистрирован: Пт сен 13, 2013 13:11:31
[uquote="WiseLord",url="/forum/viewtopic.php?p=3895364#p3895364"]При выходе эти регистры из стека уйдут, при повторном вызове фунций, снова попадут в стек и будут заполнены заново.[/uquote]
Ложное утверждение.
Если буфер DMA статический, то многие компиляторы вполне успешно умеют кешировать статические переменные в регистрах между вызовами функций. Вы даже не можете быть уверены, не заинлайнил ли компилятор Вашу функцию!
Если буфер DMA стековый (извращение, однако), то для начала, Вы получите предупреждение компилятора об обращении к неинициализированной переменной, а затем совсем не факт, что компилятор будет из этой неинициализированной переменной что-то читать. И нет никакой гарантии, что память в стеке под этот буфер вообще будет выделяться. Зачем, если под него можно выделить регистры?
Единственный надежный способ заставить компилятор читать что-то из памяти - это объявление volatile. В противном случае, оптимизатор сам решает, стоит ли вообще тратить время на обращение к памяти или обойтись регистрами.
Ложное утверждение.
Если буфер DMA статический, то многие компиляторы вполне успешно умеют кешировать статические переменные в регистрах между вызовами функций. Вы даже не можете быть уверены, не заинлайнил ли компилятор Вашу функцию!
Если буфер DMA стековый (извращение, однако), то для начала, Вы получите предупреждение компилятора об обращении к неинициализированной переменной, а затем совсем не факт, что компилятор будет из этой неинициализированной переменной что-то читать. И нет никакой гарантии, что память в стеке под этот буфер вообще будет выделяться. Зачем, если под него можно выделить регистры?
Единственный надежный способ заставить компилятор читать что-то из памяти - это объявление volatile. В противном случае, оптимизатор сам решает, стоит ли вообще тратить время на обращение к памяти или обойтись регистрами.
- Сообщения: 6457
- Зарегистрирован: Пт сен 13, 2013 13:11:31
Выдающимся специалистам по volatile втыкать до полного просвещения:
...
...

Кликабельно, если захочется подробностей.
...
...
Кликабельно, если захочется подробностей.
- Вложения
-
- volatile2.png
- (7.34 КБ) 681 скачивание
-
- volatile.png
- (32.07 КБ) 714 скачиваний
Я так и не понял суть спора о параметрах функции: с моей точки зрения тип параметра показывает то, как этот параметр трактуется функцией, т.е. как она внутри себя его использует. Никакого доступа к данным массива внутри рассматриваемой функции нет, адрес этого массива просто заносится в регистр, и все! Это уже снаружи функции важно, чтобы компилятор не оптимизировал доступ к данным, а самой функции все равно!
Я с самого начала задаю вопрос: как квалификатор volatlile повлияет на запись адреса в регистр?! Никак. Поэтому этот указатель может (и, имхо, должен) быть void*, тогда по идее никаких проблем не будет ни с какой точки зрения.
Я с самого начала задаю вопрос: как квалификатор volatlile повлияет на запись адреса в регистр?! Никак. Поэтому этот указатель может (и, имхо, должен) быть void*, тогда по идее никаких проблем не будет ни с какой точки зрения.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
- Сообщения: 6457
- Зарегистрирован: Пт сен 13, 2013 13:11:31
[uquote="ARV",url="/forum/viewtopic.php?p=3895444#p3895444"]Я с самого начала задаю вопрос: как квалификатор volatlile повлияет на запись адреса в регистр?! Никак. Поэтому этот указатель может (и, имхо, должен) быть void*, тогда по идее никаких проблем не будет ни с какой точки зрения.[/uquote]
К стм-овским индусам 100% относится уже звучавшее "Мало кто из программистов хорошо понимает, как правильно использовать volatile." Вам же, похоже, и до их квалификации как до луны. Проблемы у вас не то, что будут, они уже сейчас стоят в полный рост. Тип указателя, в данном случае, ни на что не влияет и никаких проблем не устраняет.
К стм-овским индусам 100% относится уже звучавшее "Мало кто из программистов хорошо понимает, как правильно использовать volatile." Вам же, похоже, и до их квалификации как до луны. Проблемы у вас не то, что будут, они уже сейчас стоят в полный рост. Тип указателя, в данном случае, ни на что не влияет и никаких проблем не устраняет.
не надо обсуждать мои недостатки, недостатки индусов и т.п.
почему вы не возмущаетесь функцией memset - у нее параметры тоже не volatile! хотя "по смыслу" она очень похожа на работу рассматриваемой функции с DMA.
все дело именно в описании ИНТЕРФЕЙСА функции, т.е. её параметров: как функция должна себя вести, такой должен быть и интерфейс, чтобы не вводить программиста, не знакомого с её внутренним устройством, в заблуждение. если данная функция никак от режима оптимизации не меняет своё поведение, и это можно гарантировать и для будущих версий стандартов (поскольку никак нельзя оптимизировать начальную инициализацию регистра), то и требовать для неё какого-то особого интерфейса с намеком на зависимость от оптимизации, не корректно.
Добавлено after 3 minutes 24 seconds:
кстати, о проблемах: характерный источник проблем зачастую кроется именно в том, что написано не то, что подразумевается. и в данном контексте, как я уже говорил, лучший вариант интерфейса этой функции - указатель void*, демонстрирующий полное безразличие функции к данным по этому адресу.
почему вы не возмущаетесь функцией memset - у нее параметры тоже не volatile! хотя "по смыслу" она очень похожа на работу рассматриваемой функции с DMA.
все дело именно в описании ИНТЕРФЕЙСА функции, т.е. её параметров: как функция должна себя вести, такой должен быть и интерфейс, чтобы не вводить программиста, не знакомого с её внутренним устройством, в заблуждение. если данная функция никак от режима оптимизации не меняет своё поведение, и это можно гарантировать и для будущих версий стандартов (поскольку никак нельзя оптимизировать начальную инициализацию регистра), то и требовать для неё какого-то особого интерфейса с намеком на зависимость от оптимизации, не корректно.
Добавлено after 3 minutes 24 seconds:
кстати, о проблемах: характерный источник проблем зачастую кроется именно в том, что написано не то, что подразумевается. и в данном контексте, как я уже говорил, лучший вариант интерфейса этой функции - указатель void*, демонстрирующий полное безразличие функции к данным по этому адресу.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
- Сообщения: 2567
- Зарегистрирован: Вт май 01, 2018 19:44:47
ARV, вы задаёте правильный, но очень неудобный вопрос. Именно поэтому вместо ответа на него получаете хамство и переход на личности.
За неимением HAL-а, накидал простенький пример, иллюстрирующий обсуждаемый вопрос.Посмотрим листинг?
Так и хочется процитировать классика: "Что, сынку, помогли тебе твои ляхи (volatile)?"
За неимением HAL-а, накидал простенький пример, иллюстрирующий обсуждаемый вопрос.
Спойлер
Код: Выделить всё
void foo1(uint8_t * adr)
{
DMA1_Channel1->CMAR = uint32_t(adr);
}
void foo2(volatile uint8_t * adr)
{
DMA1_Channel2->CMAR = uint32_t(adr);
}
int main()
{
uint16_t buf1 = 101;
volatile uint16_t buf2 = 102;
// Никаких проблем с функциями в любых сочетаниях нет
foo1((uint8_t *)&buf1);
foo2((uint8_t *)&buf1);
foo1((uint8_t *)&buf2);
foo2((uint8_t *)&buf2);
// Так должен себя вести буфер c DMA
GPIOA->ODR = buf2;
// А вот тут проблема!!!
GPIOA->ODR = buf1;
for(;;);
}
Спойлер
Код: Выделить всё
//void foo1(uint8_t * adr)
//{
// DMA1_Channel1->CMAR = uint32_t(adr);
_Z4foo1Ph:
LDR.N R1,??DataTable2 ;; 0x40020014
STR R0,[R1, #+0]
//}
BX LR ;; return
//void foo2(volatile uint8_t * adr)
//{
// DMA1_Channel2->CMAR = uint32_t(adr);
_Z4foo2PVh:
LDR.N R1,??DataTable2_1 ;; 0x40020028
STR R0,[R1, #+0]
//}
BX LR ;; return
//int main()
//{
main:
SUB SP,SP,#+4
// uint16_t buf1 = 101;
// volatile uint16_t buf2 = 102;;
MOVS R0,#+102
STRH R0,[SP, #+0]
// Никаких проблем с функциями в любых сочетаниях нет
// foo1((uint8_t *)&buf1);
ADD R1,SP,#+2
LDR.N R0,??DataTable2 ;; 0x40020014
STR R1,[R0, #+0]
// foo2((uint8_t *)&buf1);
STR R1,[R0, #+20]
// foo1((uint8_t *)&buf2);
STR SP,[R0, #+0]
// foo2((uint8_t *)&buf2);
STR SP,[R0, #+20]
// Так должен себя вести буфер c DMA
// GPIOA->ODR = buf2;
LDR.N R0,??DataTable2_2 ;; 0x48000014
LDRH R1,[SP, #+0]
STR R1,[R0, #+0]
// А вот тут проблема!!!
// GPIOA->ODR = buf1;
MOVS R2,#+101
STR R2,[R0, #+0]
// for(;;);
??main_0:
B.N ??main_0
//}


