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

Кто любит RISC в жизни, заходим, не стесняемся.
Ответить
Друг Кота
Аватара пользователя
Сообщения: 3385
Зарегистрирован: Пн окт 11, 2010 19:00:08

Сообщение Мурик »

a5021 про приведение типов ничего не слышали?
СКАЗОЧНИК писал(а):while ((RCC->BDCR & RCC_BDCR_LSERDY) != RCC_BDCR_LSERDY)
Ждем пока установится бит RCC_BDCR_LSERDY в RCC->BDCR.
Но это лучше делать с таймаутом. Если не будет "часового" кварца или они неисправен, программа повиснет в этом цикле.
Реклама
Друг Кота
Аватара пользователя
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск

Сообщение WiseLord »

СКАЗОЧНИК,
Если проследить цепочку макросов (для 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_BASE - это просто число 0x40021000UL
А 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;
Отсюда следует, что RCC->BDCR - это уже содержимое регистра по адресу 0x40021000 + (sizeof(uint32_t)) * 8 (т.к. нужно сделать 8 "скачков" по 4 байта по структуре, чтобы добраться до этого поля), т.е., содержимое регистра по адресу 0x40021020.
А дальше всё просто:

Код: Выделить всё

while ((RCC->BDCR & RCC_BDCR_LSERDY) != RCC_BDCR_LSERDY)
Это не более чем "провисание" в цикле всё то время, пока бит LSERDY в этом регистре не равен единице.
Оно же:

Код: Выделить всё

while ((RCC->BDCR & 0x02) != 0x02)
Контактная информация:
Реклама
Идёт направо - песнь заводит, Налево - сказку говорит.
Аватара пользователя
Сообщения: 5000
Зарегистрирован: Чт апр 21, 2011 17:55:50
Откуда: Иркутск

Сообщение СКАЗОЧНИК »

Как я понимаю, то структура это некоторый последовательный набор адресов под одним именем. Чтобы обратиться конкретно к нужному адресу используется оператор ->

только не понятно, почему обращаемся к 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
Станислав
Друг Кота
Аватара пользователя
Сообщения: 3385
Зарегистрирован: Пн окт 11, 2010 19:00:08

Сообщение Мурик »

СКАЗОЧНИК писал(а):Стабилизируется кварц, вроде как за 6 тактов своих.
Может HSE, но не LSE. Ему порой и 6 секунд мало.
Реклама
Эиком - электронные компоненты и радиодетали
Друг Кота
Сообщения: 6452
Зарегистрирован: Пт сен 13, 2013 13:11:31

Сообщение a5021 »

[uquote="Мурик",url="/forum/viewtopic.php?p=3894713#p3894713"]a5021 про приведение типов ничего не слышали?[/uquote]
Вы про бузину в огороде?
Реклама
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18682
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

a5021 писал(а):Итого имеем: передача правильного буфера вызывает возражения компиля, в то время, как передача горбухи проходит на ура.
имхо, проблема надуманная. программист должен не тупо следовать стандарту Си, а следовать логике работы программы. функция HAL_SPI_Receive_DMA занимается исключительно тем, что запускает аппаратуру на работу с памятью. аппаратуре же чихать с высокой колокольни на квалификатор адреса или на то, как описана память по этому адресу, ей важно численное значение этого адреса. что и делается при помощи uint8_t *pData. чтобы не было никаких варнингов, тут следовало бы использовать void*, что даже больше соответствует всей логике работы, как аппаратуры (требующей абстрактный адрес), так и программы (которой все равно, что за буфер).
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

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

Сообщение WiseLord »

СКАЗОЧНИК писал(а):Как я понимаю, то структура это некоторый последовательный набор адресов под одним именем
Нет. Структура - это переменная, которая группирует внутри себя другие переменные (поля). Эти переменные в памяти располагаются последовательно, возможно, выравниваясь при этом определённым образом (читать про упаковку структур). В случае регистров упаковка простая - там шаг равен 4 байтам (размерности указателя на STM32)
СКАЗОЧНИК писал(а):Чтобы обратиться конкретно к нужному адресу используется оператор ->
Нет, чтобы обратиться к конкретному полю ("вложенной" переменной), используется оператор "." (точка). А оператор "->" используется потому, что RCC - это не структура, а указатель на структуру - а для указателей используется именно такой "синтаксический сахар". Но можно было бы и через точку, разыменовав этот указатель: (*RCC).BDCR - но это не так "красиво" выглядит.
СКАЗОЧНИК писал(а):Вытаскиваем из него только нужный бит и делаем с ним != 0х02
Да, это типичный синтаксис в C для проверки того, установлен ли бит или нет. Скажем, проверить, что в переменной "x" бит 3 (0x04) установлен или сброшен, можно так:

Код: Выделить всё

if (x & 0x04 == 0x04) // проверка на бит=1
if (x & 0x04 != 0x04) // проверка на бит=0
Всё потому, что операция & (побитовое И) обнуляет все биты, кроме проверяемого(ых) (маски)

Добавлено after 3 minutes 28 seconds:
Мурик писал(а):Может HSE, но не LSE. Ему порой и 6 секунд мало.
Тут соглашусь. Первоначальная инициализация LSE может быть очень долгой (особенно если нет батарейного питания). Поэтому лучше в таком цикле проверки не висеть, а сделать что-то вроде конечного автомата для инициализации LSE, входя в инициализирующую функцию в основном цикле, например, раз в секунду, проверяя его состояние. То есть, инициализировать как бы "в фоне", делая / инициализируя параллельно более важные вещи.
Контактная информация:
Друг Кота
Сообщения: 6452
Зарегистрирован: Пт сен 13, 2013 13:11:31

Сообщение a5021 »

[uquote="ARV",url="/forum/viewtopic.php?p=3894757#p3894757"]
a5021 писал(а):Итого имеем: передача правильного буфера вызывает возражения компиля, в то время, как передача горбухи проходит на ура.
имхо, проблема надуманная. программист должен не тупо следовать стандарту Си, а следовать логике работы программы.[/uquote]
Стандарт, типа, подвинется, а компиль пусть заткнется? Самобытные техники посконного программирования?
функция HAL_SPI_Receive_DMA занимается исключительно тем,
Чем хочет пусть занимается. Она должна молча принять правильные параметры и взматериться на неправильные. Странно, но вы уже второй, кому захотелось подоказывать, что правильно будет наоборот. Осень?
Идёт направо - песнь заводит, Налево - сказку говорит.
Аватара пользователя
Сообщения: 5000
Зарегистрирован: Чт апр 21, 2011 17:55:50
Откуда: Иркутск

Сообщение СКАЗОЧНИК »

Блин, всегда знал, что у меня с указателями и структурами беда... Не понимаю их... (((
А оператор printf используется в программировании для МК? А то про него очень много в книгах, но мне показалось, что он для вывода на экран компьютера строк нужен. А в МК не всегда есть экран. Или я опять что-то не так понимаю?
Станислав
Собутыльник Кота
Аватара пользователя
Сообщения: 2516
Зарегистрирован: Пт июл 12, 2019 22:52:01

Сообщение Eddy_Em »

printf на МК только абдуринщики используют: слишком уж много ресурсов он съедает.
Linux rules! Windows must die. Здравомыслящий человек добровольно будет пользоваться мастдаем лишь в двух случаях: под дулом автомата или под влиянием анального зонда.
Я на гитхабе, в ЖЖ
Контактная информация:
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18682
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

a5021 писал(а):что правильно будет наоборот
с моей т.з. правильно будет void*. или volatile void* по-вашему правильнее? именно абстрактный адрес без указания того, что память там может меняться - void*.
a5021 писал(а):Осень?
не надо агрессии и хамства.
Eddy_Em писал(а):printf на МК только абдуринщики используют
глупости - используют те, кому собственное время дорого, а ресурсы МК дешевы.
СКАЗОЧНИК писал(а): А в МК не всегда есть экран
printf отлично используется для вывода в USART, для чего, собственно, он изначально и предназначался - вывод в последовательный поток.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

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

Сообщение a5021 »

[uquote="ARV",url="/forum/viewtopic.php?p=3894778#p3894778"]с моей т.з. правильно будет void*. или volatile void* по-вашему правильнее? именно абстрактный адрес без указания того, что память там может меняться - void*.[/uquote]
То, на какой тип здесь указатель, совершенно не важно. Это ни на что не влияет. Конечная запись этого адреса в регистр будет все равно, как 32-бита без знака. Другое дело volatile. Странно, как такие простые вещи не доходят ни с первого, ни с второго раза.
Друг Кота
Аватара пользователя
Сообщения: 6513
Зарегистрирован: Сб янв 28, 2006 22:47:24

Сообщение Asmodey »

[uquote="СКАЗОЧНИК",url="/forum/viewtopic.php?p=3894771#p3894771"]Блин, всегда знал, что у меня с указателями и структурами беда... Не понимаю их... ((([/uquote]
У меня та же беда. Я вот не понимаю, почему именно структуры использованы в файлах с описанием периферии МК?

Подозреваю, для того, чтобы обращаться к отдельным группам битов в регистрах именно как к группам, а не к отдельным битам. При том не затрагивая другие биты регистра. Вместо того чтобы изменять один за другим отдельные биты некоей группы битов в регистре с помощью поразрядного ИЛИ и И (пусть, это 4 бита отвечающие за коэффициент умножения PLL ) мы присваиваем сразу необходимое значение какому-то полю структуры от 0 до 15, и таким образом вместо 4 строчек в тексте программы получаем всего одну строчку. Моя догадка верна или нет?

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

Сообщение VladislavS »

[uquote="Asmodey",url="/forum/viewtopic.php?p=3894794#p3894794"]Я вот не понимаю, почему именно структуры использованы в файлах с описанием МК?.[/uquote]Потому что это удобно. Многие блоки периферии в чипе несколько раз присутствуют. Описывать надо лишь один блок. Удобно передавать в качестве параметра в какую-нибудь функцию с каким конкретно блоком работать.
[uquote="Asmodey",url="/forum/viewtopic.php?p=3894794#p3894794"]Моя догадка верна или нет?[/uquote]Нет. Структуры внутрь регистров не распространяются.
Друг Кота
Аватара пользователя
Сообщения: 6513
Зарегистрирован: Сб янв 28, 2006 22:47:24

Сообщение Asmodey »

Понятно.
Астролябия-сама меряет, было бы что мерять!!!
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18682
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

a5021 писал(а):Другое дело volatile
расскажите нам, как контроллер DMA изменит своё поведение от того, что получит указатель с volatile или без оного.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

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

Сообщение a5021 »

[uquote="ARV",url="/forum/viewtopic.php?p=3894860#p3894860"]расскажите нам, как контроллер DMA изменит своё поведение от того, что получит указатель с volatile или без оного.[/uquote]
Пусть вам об этом расскажет тот, у кого вы про "контроллер DMA" прочитали.
Друг Кота
Аватара пользователя
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск

Сообщение WiseLord »

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

Изображение

Итого имеем: передача правильного буфера вызывает возражения компиля, в то время, как передача горбухи проходит на ура
То есть, Вы специально зачем-то передаёте в функцию volatile буфер (хотя она принимает обычный указатель), и считаете это правильным? Ну, приведите явно к обычному указателю при вызове, и будет вам счастье без варнингов.
Контактная информация:
Друг Кота
Сообщения: 6452
Зарегистрирован: Пт сен 13, 2013 13:11:31

Сообщение a5021 »

[uquote="WiseLord",url="/forum/viewtopic.php?p=3894890#p3894890"]То есть, Вы специально зачем-то передаёте в функцию volatile буфер (хотя она принимает обычный указатель), и считаете это правильным?[/uquote]
То, что изменяемые извне переменные должны объявляться с модификатором volatile -- это не я считаю. Это единственный способ избежать множества дивных эффектов в случайные моменты времени.
Ну, приведите явно к обычному указателю при вызове, и будет вам счастье без варнингов.
Пока что я испытываю крайнее разочарование от столь бестолковых советов.
Друг Кота
Аватара пользователя
Сообщения: 3385
Зарегистрирован: Пн окт 11, 2010 19:00:08

Сообщение Мурик »

a5021 писал(а):Вы про бузину в огороде?
У вас растет бузина в огороде? :)))
WiseLord писал(а):То есть, Вы специально зачем-то передаёте в функцию volatile буфер (хотя она принимает обычный указатель), и считаете это правильным?
И я про тоже что volatile в данном случае не нужен.
a5021 писал(а):Конечная запись этого адреса в регистр будет все равно, как 32-бита без знака. Другое дело volatile.
Хотите сказать что приведя тип исключив volatile, функция работает не так как должна?
Повторюсь, для этой функции не нужен volatile.
Если не нравятся предупреждения, приводите тип. Если все равно несогласны - пишите в ST и доказывайте им что в HAL_SPI_Receive_DMA буфер должен быть с модификатором volatile.
a5021 писал(а):То, что изменяемые извне переменные должны объявляться с модификатором volatile
Вы изменяете содержимое буфера после его передачи функции и до завершения DMA транзации? :shock:
Но даже в этом случае как модуль DMA узнает что данные изменены и что он по вашему с этим должен делать?
Такое впечатление что вы не знаете в каких случаях нужен volatile и используете его везде.
a5021 писал(а):ока что я испытываю крайнее разочарование от столь бестолковых советов.
Не хотите тут получать советы - обращайтесь в техподдержку ST и требуйте чтобы у функции был модификатор volatile, аргументировано объясняя им зачем он нужен в данном случае.

И вообще, зачем вы используйте HAL? Пишите на регистрах и не будет проблем.
Ответить

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