volatile должен быть буфер, адрес которого передаётся в функцию.
STM32 новичку в ARM что к чему
- Сообщения: 2567
- Зарегистрирован: Вт май 01, 2018 19:44:47
И чего? Функции HAL_SPI_Receive_DMA на это начхать. Ей дали адрес, она туда положит (или возьмёт). Что по этому адресу ей фиолетово.
volatile должен быть буфер, адрес которого передаётся в функцию.
volatile должен быть буфер, адрес которого передаётся в функцию.
- Реклама
Собрал себе копию Stlink только сам разводил ну и по максимуму вывел все порты! у кого-то подсмотрел что выводят A2 и A3 RX и TX ну и я тоже вывел! ну как говорится про запас! запустил прошил все работает все гуд! но при обновление обратил внимание что прошивка stm8+10! Вопрос такой для чего нужен rx tx и наверно нужна какая-то другая прошивка... не-знаю не сталкивался!
качество монтажа не судите строго трясущимися руками пока лучше не могу да это первое устройство на smd.

качество монтажа не судите строго трясущимися руками пока лучше не могу да это первое устройство на smd.

- Сообщения: 6457
- Зарегистрирован: Пт сен 13, 2013 13:11:31
[uquote="VladislavS",url="/forum/viewtopic.php?p=3894178#p3894178"]И чего? Функции HAL_SPI_Receive_DMA на это начхать.[/uquote]
Это и есть зашквар. А могло быть вполне достойно, случись тамошним индусам добавить volatile.
Это и есть зашквар. А могло быть вполне достойно, случись тамошним индусам добавить volatile.
В том виде, как функция нынче объявлена в хале, никто никому ничего не должен. Компилятор нигде не единым варнингом не пискнет, если какой горе-программер под буфер простой массив определит. И все бы поменялось, случись правильно определить параметры функции. Но нет. Любители хала обязаны страдать. И это правильно.volatile должен быть буфер, адрес которого передаётся в функцию.
- Сообщения: 2567
- Зарегистрирован: Вт май 01, 2018 19:44:47
По большому счёту, действительно, никто никому ничего не должен. Задача функции передать в контроллер DMA адрес буфера и размер принимаемых данных. Ну и пнуть DMA, наверное. Она успешно делает это без всяких volatile. Где я взял адрес буфера (с генератора случайных чисел, тригонометрическими вычислениями, шифровкой с Нибиру или взял динамически в куче в конце концов) функцию волновать не должно. Как не должно волновать что я с этим буфером делал до, после и даже во время приёма. /dev/null у меня там.
- Сообщения: 6457
- Зарегистрирован: Пт сен 13, 2013 13:11:31
[uquote="VladislavS",url="/forum/viewtopic.php?p=3894550#p3894550"]По большому счёту, действительно, никто никому ничего не должен. Задача функции передать в контроллер DMA адрес буфера и размер принимаемых данных. Ну и пнуть DMA, наверное. Она успешно делает это без всяких volatile. Где я взял адрес буфера (с генератора случайных чисел, тригонометрическими вычислениями, шифровкой с Нибиру или взял динамически в куче в конце концов) функцию волновать не должно. Как не должно волновать что я с этим буфером делал до, после и даже во время приёма. /dev/null у меня там.[/uquote]
Ваше право выстрелить себе ногу, безусловно, священно, но вожделенные мечтания, чтобы попутно отстрелились еще и яйца -- это все же чутка перебор.
Ставим мысленный эксперимент. Keil, clang 6.14, все варнинги включены:

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

Итого имеем: передача правильного буфера вызывает возражения компиля, в то время, как передача горбухи проходит на ура. Вы за это? И реверс ситуации простым добавлением volatile к параметру функции вас категорически не устраивает? Хм. Я конечно понимаю, что квалификация порой навязывает танцору довольно специфичные взгляды на жизнь, но зачем же выпячивать?
Ваше право выстрелить себе ногу, безусловно, священно, но вожделенные мечтания, чтобы попутно отстрелились еще и яйца -- это все же чутка перебор.
Ставим мысленный эксперимент. Keil, clang 6.14, все варнинги включены:
Передача галимого буфера в функцию не вызывает ни у кого никаких возражений. Все ровно так, как вы любите. Но если захочется погорячее и придет в голову сделать все-таки правильно, то жгучий перчик не замедлит обнаружиться:
Итого имеем: передача правильного буфера вызывает возражения компиля, в то время, как передача горбухи проходит на ура. Вы за это? И реверс ситуации простым добавлением volatile к параметру функции вас категорически не устраивает? Хм. Я конечно понимаю, что квалификация порой навязывает танцору довольно специфичные взгляды на жизнь, но зачем же выпячивать?
- Вложения
-
- 2020-09-19_133528.jpg
- (38.37 КБ) 1077 скачиваний
-
- 2020-09-19_132828.jpg
- (21.03 КБ) 782 скачивания
- Реклама
Я понимаю, что я тупой. Переведите на русский язык пожалуйста эту строку
while ((RCC->BDCR & RCC_BDCR_LSERDY) != RCC_BDCR_LSERDY)
Понятно, что ждет установки флага готовности низкочастотного резонатора, но с позиции Си плохо ее понимаю. Плоховасто доходят до меня структуры, хотя уже много где про них читал...
while ((RCC->BDCR & RCC_BDCR_LSERDY) != RCC_BDCR_LSERDY)
Понятно, что ждет установки флага готовности низкочастотного резонатора, но с позиции Си плохо ее понимаю. Плоховасто доходят до меня структуры, хотя уже много где про них читал...
Станислав
- Сообщения: 3386
- Зарегистрирован: Пн окт 11, 2010 19:00:08
a5021 про приведение типов ничего не слышали?
Но это лучше делать с таймаутом. Если не будет "часового" кварца или они неисправен, программа повиснет в этом цикле.
Ждем пока установится бит RCC_BDCR_LSERDY в RCC->BDCR.СКАЗОЧНИК писал(а):while ((RCC->BDCR & RCC_BDCR_LSERDY) != RCC_BDCR_LSERDY)
Но это лучше делать с таймаутом. Если не будет "часового" кварца или они неисправен, программа повиснет в этом цикле.
СКАЗОЧНИК,
Если проследить цепочку макросов (для F103 серии, в моём примере), то получается так:
То есть, RCC_BASE - это просто число 0x40021000UL
А RCC - это указатель на структуру RCC_TypeDef, равный 0x40021000
Дальше,
Отсюда следует, что RCC->BDCR - это уже содержимое регистра по адресу 0x40021000 + (sizeof(uint32_t)) * 8 (т.к. нужно сделать 8 "скачков" по 4 байта по структуре, чтобы добраться до этого поля), т.е., содержимое регистра по адресу 0x40021020.
А дальше всё просто:Это не более чем "провисание" в цикле всё то время, пока бит LSERDY в этом регистре не равен единице.
Оно же:
Если проследить цепочку макросов (для F103 серии, в моём примере), то получается так:
Код: Выделить всё
#define PERIPH_BASE 0x40000000UL /*!< Peripheral base address in the alias region */
#define AHBPERIPH_BASE (PERIPH_BASE + 0x00020000UL)
#define RCC_BASE (AHBPERIPH_BASE + 0x00001000UL)
#define RCC ((RCC_TypeDef *)RCC_BASE)А RCC - это указатель на структуру RCC_TypeDef, равный 0x40021000
Дальше,
Код: Выделить всё
typedef struct
{
__IO uint32_t CR;
__IO uint32_t CFGR;
__IO uint32_t CIR;
__IO uint32_t APB2RSTR;
__IO uint32_t APB1RSTR;
__IO uint32_t AHBENR;
__IO uint32_t APB2ENR;
__IO uint32_t APB1ENR;
__IO uint32_t BDCR;
__IO uint32_t CSR;
} RCC_TypeDef;А дальше всё просто:
Код: Выделить всё
while ((RCC->BDCR & RCC_BDCR_LSERDY) != RCC_BDCR_LSERDY)Оно же:
Код: Выделить всё
while ((RCC->BDCR & 0x02) != 0x02)Как я понимаю, то структура это некоторый последовательный набор адресов под одним именем. Чтобы обратиться конкретно к нужному адресу используется оператор ->
только не понятно, почему обращаемся к RCC->BDCR, а не к RCC_TypeDef->BDCR? А, понял, оно через дефайн объявлено.
Тогда,
RCC->BDCR & 0x02
с адресом в памяти МК делаем & 0x02? Накладываем маску? Или я гоню?
Добавлено after 2 minutes 41 second:
З.Ы. и как в том цикле сделать правильно таймаут? Стабилизируется кварц, вроде как за 6 тактов своих. Считать некую переменную до некоторого значения?
Добавлено after 4 minutes:
Ой.
RCC->BDCR это же содержимое регистра... Значит на его содержимое & 0x02
Добавлено after 39 seconds:
Вытаскиваем из него только нужный бит и делаем с ним != 0х02
только не понятно, почему обращаемся к RCC->BDCR, а не к RCC_TypeDef->BDCR? А, понял, оно через дефайн объявлено.
Тогда,
RCC->BDCR & 0x02
с адресом в памяти МК делаем & 0x02? Накладываем маску? Или я гоню?
Добавлено after 2 minutes 41 second:
З.Ы. и как в том цикле сделать правильно таймаут? Стабилизируется кварц, вроде как за 6 тактов своих. Считать некую переменную до некоторого значения?
Добавлено after 4 minutes:
Ой.
RCC->BDCR это же содержимое регистра... Значит на его содержимое & 0x02
Добавлено after 39 seconds:
Вытаскиваем из него только нужный бит и делаем с ним != 0х02
Станислав
- Сообщения: 3386
- Зарегистрирован: Пн окт 11, 2010 19:00:08
Может HSE, но не LSE. Ему порой и 6 секунд мало.СКАЗОЧНИК писал(а):Стабилизируется кварц, вроде как за 6 тактов своих.
- Сообщения: 6457
- Зарегистрирован: Пт сен 13, 2013 13:11:31
[uquote="Мурик",url="/forum/viewtopic.php?p=3894713#p3894713"]a5021 про приведение типов ничего не слышали?[/uquote]
Вы про бузину в огороде?
Вы про бузину в огороде?
имхо, проблема надуманная. программист должен не тупо следовать стандарту Си, а следовать логике работы программы. функция HAL_SPI_Receive_DMA занимается исключительно тем, что запускает аппаратуру на работу с памятью. аппаратуре же чихать с высокой колокольни на квалификатор адреса или на то, как описана память по этому адресу, ей важно численное значение этого адреса. что и делается при помощи uint8_t *pData. чтобы не было никаких варнингов, тут следовало бы использовать void*, что даже больше соответствует всей логике работы, как аппаратуры (требующей абстрактный адрес), так и программы (которой все равно, что за буфер).a5021 писал(а):Итого имеем: передача правильного буфера вызывает возражения компиля, в то время, как передача горбухи проходит на ура.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
Нет. Структура - это переменная, которая группирует внутри себя другие переменные (поля). Эти переменные в памяти располагаются последовательно, возможно, выравниваясь при этом определённым образом (читать про упаковку структур). В случае регистров упаковка простая - там шаг равен 4 байтам (размерности указателя на STM32)СКАЗОЧНИК писал(а):Как я понимаю, то структура это некоторый последовательный набор адресов под одним именем
Нет, чтобы обратиться к конкретному полю ("вложенной" переменной), используется оператор "." (точка). А оператор "->" используется потому, что RCC - это не структура, а указатель на структуру - а для указателей используется именно такой "синтаксический сахар". Но можно было бы и через точку, разыменовав этот указатель: (*RCC).BDCR - но это не так "красиво" выглядит.СКАЗОЧНИК писал(а):Чтобы обратиться конкретно к нужному адресу используется оператор ->
Да, это типичный синтаксис в C для проверки того, установлен ли бит или нет. Скажем, проверить, что в переменной "x" бит 3 (0x04) установлен или сброшен, можно так:СКАЗОЧНИК писал(а):Вытаскиваем из него только нужный бит и делаем с ним != 0х02
Код: Выделить всё
if (x & 0x04 == 0x04) // проверка на бит=1
if (x & 0x04 != 0x04) // проверка на бит=0Добавлено after 3 minutes 28 seconds:
Тут соглашусь. Первоначальная инициализация LSE может быть очень долгой (особенно если нет батарейного питания). Поэтому лучше в таком цикле проверки не висеть, а сделать что-то вроде конечного автомата для инициализации LSE, входя в инициализирующую функцию в основном цикле, например, раз в секунду, проверяя его состояние. То есть, инициализировать как бы "в фоне", делая / инициализируя параллельно более важные вещи.Мурик писал(а):Может HSE, но не LSE. Ему порой и 6 секунд мало.
- Сообщения: 6457
- Зарегистрирован: Пт сен 13, 2013 13:11:31
[uquote="ARV",url="/forum/viewtopic.php?p=3894757#p3894757"]
Стандарт, типа, подвинется, а компиль пусть заткнется? Самобытные техники посконного программирования?
имхо, проблема надуманная. программист должен не тупо следовать стандарту Си, а следовать логике работы программы.[/uquote]a5021 писал(а):Итого имеем: передача правильного буфера вызывает возражения компиля, в то время, как передача горбухи проходит на ура.
Стандарт, типа, подвинется, а компиль пусть заткнется? Самобытные техники посконного программирования?
Чем хочет пусть занимается. Она должна молча принять правильные параметры и взматериться на неправильные. Странно, но вы уже второй, кому захотелось подоказывать, что правильно будет наоборот. Осень?функция HAL_SPI_Receive_DMA занимается исключительно тем,
Блин, всегда знал, что у меня с указателями и структурами беда... Не понимаю их... (((
А оператор printf используется в программировании для МК? А то про него очень много в книгах, но мне показалось, что он для вывода на экран компьютера строк нужен. А в МК не всегда есть экран. Или я опять что-то не так понимаю?
А оператор printf используется в программировании для МК? А то про него очень много в книгах, но мне показалось, что он для вывода на экран компьютера строк нужен. А в МК не всегда есть экран. Или я опять что-то не так понимаю?
Станислав
- Сообщения: 2516
- Зарегистрирован: Пт июл 12, 2019 22:52:01
с моей т.з. правильно будет void*. или volatile void* по-вашему правильнее? именно абстрактный адрес без указания того, что память там может меняться - void*.a5021 писал(а):что правильно будет наоборот
не надо агрессии и хамства.a5021 писал(а):Осень?
глупости - используют те, кому собственное время дорого, а ресурсы МК дешевы.Eddy_Em писал(а):printf на МК только абдуринщики используют
printf отлично используется для вывода в USART, для чего, собственно, он изначально и предназначался - вывод в последовательный поток.СКАЗОЧНИК писал(а): А в МК не всегда есть экран
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
- Сообщения: 6457
- Зарегистрирован: Пт сен 13, 2013 13:11:31
[uquote="ARV",url="/forum/viewtopic.php?p=3894778#p3894778"]с моей т.з. правильно будет void*. или volatile void* по-вашему правильнее? именно абстрактный адрес без указания того, что память там может меняться - void*.[/uquote]
То, на какой тип здесь указатель, совершенно не важно. Это ни на что не влияет. Конечная запись этого адреса в регистр будет все равно, как 32-бита без знака. Другое дело volatile. Странно, как такие простые вещи не доходят ни с первого, ни с второго раза.
То, на какой тип здесь указатель, совершенно не важно. Это ни на что не влияет. Конечная запись этого адреса в регистр будет все равно, как 32-бита без знака. Другое дело volatile. Странно, как такие простые вещи не доходят ни с первого, ни с второго раза.
- Сообщения: 7058
- Зарегистрирован: Сб янв 28, 2006 22:47:24
[uquote="СКАЗОЧНИК",url="/forum/viewtopic.php?p=3894771#p3894771"]Блин, всегда знал, что у меня с указателями и структурами беда... Не понимаю их... ((([/uquote]
У меня та же беда. Я вот не понимаю, почему именно структуры использованы в файлах с описанием периферии МК?
Подозреваю, для того, чтобы обращаться к отдельным группам битов в регистрах именно как к группам, а не к отдельным битам. При том не затрагивая другие биты регистра. Вместо того чтобы изменять один за другим отдельные биты некоей группы битов в регистре с помощью поразрядного ИЛИ и И (пусть, это 4 бита отвечающие за коэффициент умножения PLL ) мы присваиваем сразу необходимое значение какому-то полю структуры от 0 до 15, и таким образом вместо 4 строчек в тексте программы получаем всего одну строчку. Моя догадка верна или нет?
А примеры работы со структурами с printf для PC, которыми пестрит интернет, действительно не очень-то наглядны применительно к МК.
У меня та же беда. Я вот не понимаю, почему именно структуры использованы в файлах с описанием периферии МК?
Подозреваю, для того, чтобы обращаться к отдельным группам битов в регистрах именно как к группам, а не к отдельным битам. При том не затрагивая другие биты регистра. Вместо того чтобы изменять один за другим отдельные биты некоей группы битов в регистре с помощью поразрядного ИЛИ и И (пусть, это 4 бита отвечающие за коэффициент умножения PLL ) мы присваиваем сразу необходимое значение какому-то полю структуры от 0 до 15, и таким образом вместо 4 строчек в тексте программы получаем всего одну строчку. Моя догадка верна или нет?
А примеры работы со структурами с printf для PC, которыми пестрит интернет, действительно не очень-то наглядны применительно к МК.
Астролябия-сама меряет, было бы что мерять!!!
- Сообщения: 2567
- Зарегистрирован: Вт май 01, 2018 19:44:47
[uquote="Asmodey",url="/forum/viewtopic.php?p=3894794#p3894794"]Я вот не понимаю, почему именно структуры использованы в файлах с описанием МК?.[/uquote]Потому что это удобно. Многие блоки периферии в чипе несколько раз присутствуют. Описывать надо лишь один блок. Удобно передавать в качестве параметра в какую-нибудь функцию с каким конкретно блоком работать.
[uquote="Asmodey",url="/forum/viewtopic.php?p=3894794#p3894794"]Моя догадка верна или нет?[/uquote]Нет. Структуры внутрь регистров не распространяются.
[uquote="Asmodey",url="/forum/viewtopic.php?p=3894794#p3894794"]Моя догадка верна или нет?[/uquote]Нет. Структуры внутрь регистров не распространяются.


