STM32 новичку в ARM что к чему

Кто любит RISC в жизни, заходим, не стесняемся.
Ответить
Друг Кота
Сообщения: 6452
Зарегистрирован: Пт сен 13, 2013 13:11:31

Сообщение a5021 »

[uquote="WiseLord",url="/forum/viewtopic.php?p=3895325#p3895325"]Нет, это просто Вы передаёте ей неверные параметры.[/uquote]
Эти "неверные" ?

Изображение

Просите Мурика, быть может он сжалится и вышлет вам букварь про волатайл повторно.
Реклама
Друг Кота
Аватара пользователя
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск

Сообщение WiseLord »

Да, неверные. Функция хочет указатель на uint8_t, а её передаётся массив volatile uint8_t. Вы используете функцию не по назначению.

Это как если бы в функцию, принимающую строку я захотел бы передать int. Ну вот просто потому, что считаю - что int - это good, а строки - это bad. Правда, тут warning-ом бы не обошлось - но это и бзик побольше.

P.S. По третьему примеру явно видно, что проблема не в функции, а в самом good_buffer:

Изображение
Контактная информация:
Реклама
Друг Кота
Сообщения: 6452
Зарегистрирован: Пт сен 13, 2013 13:11:31

Сообщение a5021 »

[uquote="WiseLord",url="/forum/viewtopic.php?p=3895340#p3895340"]Да, неверные. Функция хочет указатель на uint8_t, а её передаётся массив volatile uint8_t. Вы используете функцию не по назначению.[/uquote]
Для вас, поди, новость еще и то, что под DMA-трансфер переменная должна быть объявлена, как volatile ?
Друг Кота
Аватара пользователя
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск

Сообщение WiseLord »

Не должна.

P.S. Чтобы это звучало голословно, простой пример: периодически считываем результат преобразования АЦП микроконтроллера в буфер из, скажем, 4 элементов, постоянно и циклически. Цель иметь усредненённое значение последних 4 измерений, чтобы уменьшить шум преобразования. Тут совершенно не нужен volatile.
Контактная информация:
Реклама
Эиком - электронные компоненты и радиодетали
Друг Кота
Сообщения: 6452
Зарегистрирован: Пт сен 13, 2013 13:11:31

Сообщение a5021 »

[uquote="WiseLord",url="/forum/viewtopic.php?p=3895346#p3895346"]Не должна.

P.S. Чтобы это звучало голословно, простой пример: периодически считываем результат преобразования АЦП микроконтроллера в буфер из, скажем, 4 элементов, постоянно и циклически. Цель иметь усредненённое значение последних 4 измерений, чтобы уменьшить шум преобразования. Тут совершенно не нужен volatile.[/uquote]
Вот эта ваша "не должна", она работает только для вашего примера или для любых случаев?
Реклама
Собутыльник Кота
Аватара пользователя
Сообщения: 2723
Зарегистрирован: Пт сен 07, 2018 20:20:02
Откуда: деревня в Тульской губернии

Сообщение ПростоНуб »

[uquote="WiseLord",url="/forum/viewtopic.php?p=3895346#p3895346"]Тут совершенно не нужен volatile.[/uquote]
Прошу прощения, но с чего вы решили, что компилятор не закеширует значение всех четырех измерений в регистрах и Вы в итоге не будете получать один и тот же результат, вообще не зависящий от результатов преобразования АЦП?
Реклама
Друг Кота
Аватара пользователя
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск

Сообщение WiseLord »

a5021 писал(а):Вот эта ваша "не должна", она работает только для вашего примера или для любых случаев?
Одного опровергающего примера уже достаточно, чтобы общее утверждение "DMA буфер должен быть всегда volatile" стало ложным.

Добавлено after 3 minutes 26 seconds:
ПростоНуб писал(а):с чего вы решили, что компилятор не закеширует значение всех четырех измерений в регистрах
Хотя бы с того, что в функции они мне нужны только один раз - прочитать и усреднить. При выходе эти регистры из стека уйдут, при повторном вызове фунций, снова попадут в стек и будут заполнены заново.
Контактная информация:
Друг Кота
Сообщения: 6452
Зарегистрирован: Пт сен 13, 2013 13:11:31

Сообщение a5021 »

Феерический бред
Собутыльник Кота
Аватара пользователя
Сообщения: 2723
Зарегистрирован: Пт сен 07, 2018 20:20:02
Откуда: деревня в Тульской губернии

Сообщение ПростоНуб »

[uquote="WiseLord",url="/forum/viewtopic.php?p=3895364#p3895364"]При выходе эти регистры из стека уйдут, при повторном вызове фунций, снова попадут в стек и будут заполнены заново.[/uquote]
Ложное утверждение.
Если буфер DMA статический, то многие компиляторы вполне успешно умеют кешировать статические переменные в регистрах между вызовами функций. Вы даже не можете быть уверены, не заинлайнил ли компилятор Вашу функцию!
Если буфер DMA стековый (извращение, однако), то для начала, Вы получите предупреждение компилятора об обращении к неинициализированной переменной, а затем совсем не факт, что компилятор будет из этой неинициализированной переменной что-то читать. И нет никакой гарантии, что память в стеке под этот буфер вообще будет выделяться. Зачем, если под него можно выделить регистры?
Единственный надежный способ заставить компилятор читать что-то из памяти - это объявление volatile. В противном случае, оптимизатор сам решает, стоит ли вообще тратить время на обращение к памяти или обойтись регистрами.
Друг Кота
Сообщения: 6452
Зарегистрирован: Пт сен 13, 2013 13:11:31

Сообщение a5021 »

Выдающимся специалистам по volatile втыкать до полного просвещения:

Изображение

...
...

Изображение

Кликабельно, если захочется подробностей.
Вложения
volatile2.png
(7.34 КБ) 660 скачиваний
volatile.png
(32.07 КБ) 691 скачивание
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18682
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

Я так и не понял суть спора о параметрах функции: с моей точки зрения тип параметра показывает то, как этот параметр трактуется функцией, т.е. как она внутри себя его использует. Никакого доступа к данным массива внутри рассматриваемой функции нет, адрес этого массива просто заносится в регистр, и все! Это уже снаружи функции важно, чтобы компилятор не оптимизировал доступ к данным, а самой функции все равно!
Я с самого начала задаю вопрос: как квалификатор volatlile повлияет на запись адреса в регистр?! Никак. Поэтому этот указатель может (и, имхо, должен) быть void*, тогда по идее никаких проблем не будет ни с какой точки зрения.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Друг Кота
Сообщения: 6452
Зарегистрирован: Пт сен 13, 2013 13:11:31

Сообщение a5021 »

[uquote="ARV",url="/forum/viewtopic.php?p=3895444#p3895444"]Я с самого начала задаю вопрос: как квалификатор volatlile повлияет на запись адреса в регистр?! Никак. Поэтому этот указатель может (и, имхо, должен) быть void*, тогда по идее никаких проблем не будет ни с какой точки зрения.[/uquote]
К стм-овским индусам 100% относится уже звучавшее "Мало кто из программистов хорошо понимает, как правильно использовать volatile." Вам же, похоже, и до их квалификации как до луны. Проблемы у вас не то, что будут, они уже сейчас стоят в полный рост. Тип указателя, в данном случае, ни на что не влияет и никаких проблем не устраняет.
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18682
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

не надо обсуждать мои недостатки, недостатки индусов и т.п.
почему вы не возмущаетесь функцией memset - у нее параметры тоже не volatile! хотя "по смыслу" она очень похожа на работу рассматриваемой функции с DMA.

все дело именно в описании ИНТЕРФЕЙСА функции, т.е. её параметров: как функция должна себя вести, такой должен быть и интерфейс, чтобы не вводить программиста, не знакомого с её внутренним устройством, в заблуждение. если данная функция никак от режима оптимизации не меняет своё поведение, и это можно гарантировать и для будущих версий стандартов (поскольку никак нельзя оптимизировать начальную инициализацию регистра), то и требовать для неё какого-то особого интерфейса с намеком на зависимость от оптимизации, не корректно.

Добавлено after 3 minutes 24 seconds:
кстати, о проблемах: характерный источник проблем зачастую кроется именно в том, что написано не то, что подразумевается. и в данном контексте, как я уже говорил, лучший вариант интерфейса этой функции - указатель void*, демонстрирующий полное безразличие функции к данным по этому адресу.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Собутыльник Кота
Аватара пользователя
Сообщения: 2562
Зарегистрирован: Вт май 01, 2018 19:44:47

Сообщение VladislavS »

ARV, вы задаёте правильный, но очень неудобный вопрос. Именно поэтому вместо ответа на него получаете хамство и переход на личности.

За неимением 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
//}
Так и хочется процитировать классика: "Что, сынку, помогли тебе твои ляхи (volatile)?"
Друг Кота
Сообщения: 6452
Зарегистрирован: Пт сен 13, 2013 13:11:31

Сообщение a5021 »

[uquote="ARV",url="/forum/viewtopic.php?p=3895450#p3895450"]почему вы не возмущаетесь функцией memset - у нее параметры тоже не volatile! хотя "по смыслу" она очень похожа на работу рассматриваемой функции с DMA.[/uquote]
Для кого-то похожа, для кого-то нет. И очевидно есть веские обстоятельства, почему так.

memset меняет значение области памяти в текущем программном контексте. Компилятор знает что изменяется и в какой момент времени. В случае с дма-трансфером у компилятора нет информации о том, что какая-то область памяти подвергнется изменениям или эта область будет как-то использована. Если не "зажать" область памяти (переменную) с помощью volatile, то компилятор может попытаться соптимизировать, высвободить или переиспользовать это пространство со всеми вытекающими. Вы подготовили буфер к отправке, передали указатели в блок DMA, но к моменту, когда дело дойдет до реальной передачи, эта область памяти может быть использована компилятором по своему, а не вашему усмотрению.
кстати, о проблемах: характерный источник проблем зачастую кроется именно в том, что написано не то, что подразумевается. и в данном контексте, как я уже говорил, лучший вариант интерфейса этой функции - указатель void*, демонстрирующий полное безразличие функции к данным по этому адресу.
Что вы заладили с этим своим воидом. Не играет оно тут никакой роли.

[uquote="VladislavS",url="/forum/viewtopic.php?p=3895477#p3895477"]ARV, вы задаёте правильный, но очень неудобный вопрос.[/uquote]
Вам он что-ли неудобный? То, что правильное значение указателя будет записано в CPAR/CMAR независимо от наличия volatile в параметрах фунции, ежу понятно и никогда и ни кем здесь не оспаривалось. Вы что и кому доказываете здесь с упорством, достойным лучшего применения?
За неимением HAL-а, накидал простенький пример, иллюстрирующий обсуждаемый вопрос.
Чепуху вы в очередной раз накидали. Пламенный ответ на вопрос, который вам никто не задавал.
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18682
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

a5021 писал(а): Вы подготовили буфер к отправке, передали указатели в блок DMA, но к моменту, когда дело дойдет до реальной передачи, эта область памяти может быть использована компилятором по своему, а не вашему усмотрению.
это может (???) произойти, как понимаю, уже после того, как злосчастная функция отработает, ведь она ничего, кроме записи в несколько регистров аппаратуты, не делает - верно? так зачем самой функции требовать volatile-буфер, если ей на это плевать? внутри этой функции никакой оптимизации нет и быть не может - там ДАННЫЕ не используются от слова вообще! нужно volatile снаружи функции или нет - вопрос другой, речь о параметрах функции!

и, если честно, я как-то не очень понимаю: как может компилятор модифицировать область памяти, которую я выделил в программе, без моего ведома?! тут явно какой-то подвох...

Добавлено after 15 minutes 3 seconds:
кстати, в MinGW GCC функция memset получает именно void*, потому и не ругается на любой буфер.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Собутыльник Кота
Аватара пользователя
Сообщения: 2516
Зарегистрирован: Пт июл 12, 2019 22:52:01

Сообщение Eddy_Em »

[uquote="a5021",url="/forum/viewtopic.php?p=3895322#p3895322"]Судя по тому, какое количество фанатов хала понабежало, говорить такие вещи здесь -- пустое дело.[/uquote]
Если не хочешь смущать людей вонью, то не стоит нырять в кучу с навозом!
Linux rules! Windows must die. Здравомыслящий человек добровольно будет пользоваться мастдаем лишь в двух случаях: под дулом автомата или под влиянием анального зонда.
Я на гитхабе, в ЖЖ
Контактная информация:
Собутыльник Кота
Аватара пользователя
Сообщения: 2562
Зарегистрирован: Вт май 01, 2018 19:44:47

Сообщение VladislavS »

[uquote="a5021",url="/forum/viewtopic.php?p=3895656#p3895656"]Пламенный ответ на вопрос, который вам никто не задавал.[/uquote]Зато вам ARV его раза три задал, но ответа не получил. А я к тому же показал, что volatile в параметрах функции никак не повлиял на возможность завести !volatile буфер. А так кмк самой функции он кмк собаке пятая нога, то и применять его там никакого смысла нет.

[uquote="ARV",url="/forum/viewtopic.php?p=3895670#p3895670"]и, если честно, я как-то не очень понимаю: как может компилятор модифицировать область памяти, которую я выделил в программе, без моего ведома?! тут явно какой-то подвох...[/uquote]А он и не меняет. Он наоборот не использует или не меняет её содержимое, ошибочно полагая, что знает что там. Или даже вообще не выделяет память, если думает, что может обойтись регистром или константой.

[uquote="Eddy_Em",url="/forum/viewtopic.php?p=3895690#p3895690"][uquote="a5021",url="/forum/viewtopic.php?p=3895322#p3895322"]Судя по тому, какое количество фанатов хала понабежало, говорить такие вещи здесь -- пустое дело.[/uquote]
Если не хочешь смущать людей вонью, то не стоит нырять в кучу с навозом![/uquote]А можно поинтересоваться, кто из участников дискуссии им пользуется? Пока что я наблюдаю лишь одного "искателя багов". Я, например, до сего дня и не подозревал о существовании такой функции. :dont_know:
Последний раз редактировалось VladislavS Пн сен 21, 2020 20:21:22, всего редактировалось 1 раз.
Друг Кота
Сообщения: 6452
Зарегистрирован: Пт сен 13, 2013 13:11:31

Сообщение a5021 »

[uquote="ARV",url="/forum/viewtopic.php?p=3895670#p3895670"]так зачем самой функции требовать volatile-буфер, если ей на это плевать?[/uquote]
Не надо ничего требовать. Вопросов бы не было, если бы она, функция, не провоцировала ложный шухер в то самое время, когда все по канону.
и, если честно, я как-то не очень понимаю: как может компилятор модифицировать область памяти, которую я выделил в программе, без моего ведома?! тут явно какой-то подвох...
А код, который вы со всем тщанием и трепетом собственноручно начертали можно выбрасывать? Так выбрасывает же. Выбрасывает в любом объеме, если сочтет бесполезным. Оптимизация называется.
кстати, в MinGW GCC функция memset получает именно void*, потому и не ругается на любой буфер.
На колу мочало...

[uquote="VladislavS",url="/forum/viewtopic.php?p=3895694#p3895694"]Зато вам ARV его раза три задал, но ответа не получил.[/uquote]
И вы решили на его вопрос ответить за меня? Кому как, конечно, но лично у меня доброхоты вызывают легкое недоверие.
А так кмк самой функции он кмк собаке пятая нога, то и применять его там никакого смысла нет.
Сама функция тут вообще ни при делах, отчего я не собирался и не собираюсь обсуждать ее вовсе. Корень проблемы в том, как объявлены параметры этой функции. Это приводят к ложной генерации предупреждений там, где их быть не должно и молчаливого одобрения там, где открывается направление к совершению ошибочных действий. Это своего рода ловушка и весь кисляк в том, что ее почти никто не видит, даже если тыкать носом. Квалификация-с.
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18682
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

VladislavS писал(а):Или даже вообще не выделяет память, если думает, что может обойтись регистром или константой.
то есть вы хотите сказать, что если я напишу static char buf[128]; то компилятор сможет его "соптимизировать", даже если я использую ссылку на него?! по-моему, это уже из области фантастики. тем более, если я этот самый buf получил из malloc

другое дело, если я ни разу не использовал в коде buf - тут да, может и выкинуть даже вызов malloc. но ведь здесь явно не тот случай рассматривается...
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Ответить

Вернуться в «ARM»