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

Кто любит RISC в жизни, заходим, не стесняемся.
Ответить
afz
Опытный кот
Аватара пользователя
Сообщения: 744
Зарегистрирован: Сб дек 22, 2012 08:17:42
Откуда: Караганда, Казахстан

Сообщение afz »

ОК, спасибо.
Кто мешает тебе выдумать порох непромокаемый? (К. Прутков, мысль № 133)
Реклама
Друг Кота
Сообщения: 6457
Зарегистрирован: Пт сен 13, 2013 13:11:31

Сообщение a5021 »

На хабре появилась статеечка, как ручками через регистры сконфигурировать тактирование на STM32H7. Никогда ранее с седьмой серией не сталкивался, но что и зачем делает автор в общих чертах понятно. Кроме одного момента:

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

//PLLM = 4
	RCC -> PLLCKSELR &= ~RCC_PLLCKSELR_DIVM1_5; //0
	RCC -> PLLCKSELR &= ~RCC_PLLCKSELR_DIVM1_4; //0
	RCC -> PLLCKSELR &= ~RCC_PLLCKSELR_DIVM1_3; //0
	RCC -> PLLCKSELR |=  RCC_PLLCKSELR_DIVM1_2; //1
	RCC -> PLLCKSELR &= ~RCC_PLLCKSELR_DIVM1_1; //0
	RCC -> PLLCKSELR &= ~RCC_PLLCKSELR_DIVM1_0; //0
Занесение значения в регистр RCC_PLLCKSELR зачем-то разбито аж на шесть шагов. Никто не в курсе, зачем все это и почему нельзя было написать просто

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

RCC -> PLLCKSELR =  RCC_PLLCKSELR_DIVM1_2;
?
Реклама
Друг Кота
Аватара пользователя
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск

Сообщение WiseLord »

Видимо, потому что такой "сложный" способ не затрагивает остальные биты регистра RCC->PLLCKSELR. В отличие от "простого", обнуляющего их.
Контактная информация:
Друг Кота
Сообщения: 6457
Зарегистрирован: Пт сен 13, 2013 13:11:31

Сообщение a5021 »

Да фиг с ними, с остальными. Я про то, что при первоначальной инициализации можно все эти "остальные" загонять в регистр одним присваиванием. Какой смысл перещелкивать битики по одному в то время, когда PLL даже не включен, а само состояние этих битиков известно? Автор, судя по его статьям на хабре, не похож на неофита, но то, что он делает я объяснить себе не могу. По моим представлениям -- это полная бессмыслица.
Реклама
Эиком - электронные компоненты и радиодетали
Собутыльник Кота
Аватара пользователя
Сообщения: 2567
Зарегистрирован: Вт май 01, 2018 19:44:47

Сообщение VladislavS »

Мне попадалась следующая аргументация:
- мне так понятнее/удобнее/красивее;
- ты что память экономишь? Там её хоть опой кушай;
- опять ты со своим "=", пиши как хочешь.

А в твоём примере даже не на 6 шагов, а на 18 разбито! 6*(чтение, логическая операция, запись).

Давай в ассемблерных командах посчитаем:
- загрузка адреса регистра 1 шт.
- чтение регистра 6 шт.
- загрузка константы 6 шт.
- логическая операция 6 шт.
- запись регистра 6 шт.
ИТОГО: 25 команд.

Если откинуть команду загрузки адреса регистра, так как в предыдущих командах мы наверняка с RCC уже работали (включали HSE наверняка), то соотношение получается 24:2. В 12 раз, Карл!
Последний раз редактировалось VladislavS Пт окт 26, 2018 06:58:20, всего редактировалось 1 раз.
Реклама
Друг Кота
Аватара пользователя
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск

Сообщение WiseLord »

На самом деле, работать с битами регистра не затрагивая остальные - это достаточно важный принцип. Хотя, если речь идёт об изначальной "только один раз" инициализации на старте, можно и попроще.

Хотя я бы данный код расписал бы скорее так

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

RCC->PLLCKSELR &= ~(RCC_PLLCKSELR_DVMI1_MASK);
RCC->PLLCKSELR |= RCC_PLLCKSELR_DIVM1_2;
Не знаю, существует ли такая маска в CMSIS макросах. Если нет - сделал бы свою.
Контактная информация:
Реклама
Собутыльник Кота
Аватара пользователя
Сообщения: 2567
Зарегистрирован: Вт май 01, 2018 19:44:47

Сообщение VladislavS »

Ещё один.:) Боишься биты попортить - напиши так

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

 RCC->PLLCKSELR = (RCC->PLLCKSELR & ~RCC_PLLCKSELR_DVMI1_MASK) |  RCC_PLLCKSELR_DIVM1_2;  
Потому что запись промежуточного состояния с занулеными битами в общем случае может дать побочный эффект.
Друг Кота
Аватара пользователя
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск

Сообщение WiseLord »

И в чём принципиальное отличие от моего варианта, кроме того, что здесь это в виде одной длинной строки?
Контактная информация:
Друг Кота
Аватара пользователя
Сообщения: 3604
Зарегистрирован: Пн июл 28, 2008 22:12:01

Сообщение dosikus »

[uquote="a5021",url="/forum/viewtopic.php?p=3491273#p3491273"]Занесение значения в регистр RCC_PLLCKSELR зачем-то разбито аж на шесть шагов. Никто не в курсе, зачем все это и почему нельзя было написать просто

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

RCC -> PLLCKSELR =  RCC_PLLCKSELR_DIVM1_2;
?[/uquote]

Тяжелое наследие 8ми биток.
Первый раз сказал Мяу!
Сообщения: 32
Зарегистрирован: Вс ноя 13, 2016 18:04:13

Сообщение AlDr70 »

Ребята, скажите такой вопрос. В РМ на 103 контроллер есть таблица электрических параметров. Что такое инжектированный ток injected current?
Вложения
вопрос.pdf
current haracteristics
(364.81 КБ) 260 скачиваний
Друг Кота
Сообщения: 6457
Зарегистрирован: Пт сен 13, 2013 13:11:31

Сообщение a5021 »

[uquote="WiseLord",url="/forum/viewtopic.php?p=3491563#p3491563"]И в чём принципиальное отличие от моего варианта, кроме того, что здесь это в виде одной длинной строки?[/uquote]
Код, который варит компилятор, между тем, получается разный. В первом случае:

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

     86            RCC->PLLCKSELR &= ~(RCC_PLLCKSELR_DIVM1);
   \        0x6   0x....             LDR.N    R0,??DataTable1  ;; 0x58024428
   \        0x8   0x6801             LDR      R1,[R0, #+0]
   \        0xA   0xF421 0x717C      BIC      R1,R1,#0x3F0
   \        0xE   0x6001             STR      R1,[R0, #+0]
     87            RCC->PLLCKSELR |= RCC_PLLCKSELR_DIVM1_2;
   \       0x10   0x6802             LDR      R2,[R0, #+0]
   \       0x12   0xF042 0x0240      ORR      R2,R2,#0x40
   \       0x16   0x6002             STR      R2,[R0, #+0]
     88          
и во втором:

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

     86            RCC->PLLCKSELR = (RCC->PLLCKSELR & ~(RCC_PLLCKSELR_DIVM1)) | RCC_PLLCKSELR_DIVM1_2;
   \        0x6   0x....             LDR.N    R0,??DataTable1  ;; 0x58024428
   \        0x8   0x6801             LDR      R1,[R0, #+0]
   \        0xA   0xF421 0x717C      BIC      R1,R1,#0x3F0
   \        0xE   0xF041 0x0140      ORR      R1,R1,#0x40
   \       0x12   0x6001             STR      R1,[R0, #+0]
Разница, безусловно, не принципиальна, но смысла писать громоздким образом тоже никакого.
Собутыльник Кота
Аватара пользователя
Сообщения: 2567
Зарегистрирован: Вт май 01, 2018 19:44:47

Сообщение VladislavS »

[uquote="WiseLord",url="/forum/viewtopic.php?p=3491563#p3491563"]И в чём принципиальное отличие от моего варианта, кроме того, что здесь это в виде одной длинной строки?[/uquote]Вы правда не видите разницу между "=" и последовательными "&=" и "|=" ?
Друг Кота
Аватара пользователя
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск

Сообщение WiseLord »

Принципиальной - не вижу. Это не критичный к скорости участок кода, выполняется только один раз. Ну, будет read-modify-write дважды выполнен, а не один раз.. что с того? Читабельность кода зато отличается.
Контактная информация:
Собутыльник Кота
Аватара пользователя
Сообщения: 2567
Зарегистрирован: Вт май 01, 2018 19:44:47

Сообщение VladislavS »

[uquote="AlDr70",url="/forum/viewtopic.php?p=3491661#p3491661"]Ребята, скажите такой вопрос. В РМ на 103 контроллер есть таблица электрических параметров. Что такое инжектированный ток injected current?[/uquote]
Входящий ток. Например, если ты светодиод анодом на плюс, а катодом на ножку контроллера. Подал "0" и можешь 5 мА на землю брякнуть.
Друг Кота
Сообщения: 6457
Зарегистрирован: Пт сен 13, 2013 13:11:31

Сообщение a5021 »

[uquote="WiseLord",url="/forum/viewtopic.php?p=3491692#p3491692"]Принципиальной - не вижу. Это не критичный к скорости участок кода, выполняется только один раз. Ну, будет read-modify-write дважды выполнен, а не один раз.. что с того? Читабельность кода зато отличается.[/uquote]
По мне, так наиболее читабельной будет вот такая запись:
Спойлер

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

     86            RCC->PLLCKSELR = (
     87              0 * RCC_PLLCKSELR_PLLSRC_HSI  |
     88              0 * RCC_PLLCKSELR_PLLSRC_CSI  |
     89              1 * RCC_PLLCKSELR_PLLSRC_HSE  |
     90          
     91              0 * RCC_PLLCKSELR_DIVM1_0     |
     92              0 * RCC_PLLCKSELR_DIVM1_1     |
     93              1 * RCC_PLLCKSELR_DIVM1_2     |
     94              0 * RCC_PLLCKSELR_DIVM1_3     |
     95              0 * RCC_PLLCKSELR_DIVM1_4     |
     96              0 * RCC_PLLCKSELR_DIVM1_5     |
     97          
     98              0 * RCC_PLLCKSELR_DIVM2_0     |
     99              0 * RCC_PLLCKSELR_DIVM2_1     |
    100              0 * RCC_PLLCKSELR_DIVM2_2     |
    101              0 * RCC_PLLCKSELR_DIVM2_3     |
    102              0 * RCC_PLLCKSELR_DIVM2_4     |
    103              1 * RCC_PLLCKSELR_DIVM2_5     |
    104          
    105              0 * RCC_PLLCKSELR_DIVM3_0     |
    106              0 * RCC_PLLCKSELR_DIVM3_1     |
    107              0 * RCC_PLLCKSELR_DIVM3_2     |
    108              0 * RCC_PLLCKSELR_DIVM3_3     |
    109              0 * RCC_PLLCKSELR_DIVM3_4     |
    110              1 * RCC_PLLCKSELR_DIVM3_5
    111            );
   \        0x6   0x....             LDR.N    R0,??DataTable1  ;; 0x2020042
   \        0x8   0x....             LDR.N    R1,??DataTable1_1  ;; 0x58024428
   \        0xA   0x6008             STR      R0,[R1, #+0]
    112          
она же дает самый быстрый и компактный код. Только мой изначальный вопрос так и остается без ответа -- нафига ж сложно и громоздко, если можно просто и компактно?
Собутыльник Кота
Аватара пользователя
Сообщения: 2567
Зарегистрирован: Вт май 01, 2018 19:44:47

Сообщение VladislavS »

А я бы вот так написал

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

RCC->PLLCKSELR = RCC_PLLCKSELR_PLLSRC_HSE | _VAL2FLD(RCC_PLLCKSELR_DIVM1,4) | _VAL2FLD(RCC_PLLCKSELR_DIVM2,32)  | _VAL2FLD(RCC_PLLCKSELR_DIVM3,32);
а ещё лучше вообще определить _RCC_PLLCKSELR_DIVM1() и вот так

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

RCC->PLLCKSELR = RCC_PLLCKSELR_PLLSRC_HSE | _RCC_PLLCKSELR_DIVM1(4) | _RCC_PLLCKSELR_DIVM2(32)  | _RCC_PLLCKSELR_DIVM3(32);
Друг Кота
Сообщения: 6457
Зарегистрирован: Пт сен 13, 2013 13:11:31

Сообщение a5021 »

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

Сообщение VladislavS »

Это не магические числа, а реальные коэффициенты деления. Можно подумать, задавая поразрядно эти магические числа ты много меняешь. В случае, если это не реальные коэффициенты, а магические числа, то конечно надо их задефайнить в реальные.

Вот, например, от 411-го.

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

RCC->PLLCFGR = _RCC_PLLCFGR_PLLQ(4) | RCC_PLLCFGR_PLLSRC_HSE | RCC_PLLCFGR_PLLP_div2 | _RCC_PLLCFGR_PLLN(96) | _RCC_PLLCFGR_PLLM(4);
Никакие это не магические числа, а Q=4, N=96 и M=4. Куда уж понятней? Нафига их поразрядно задавать?
Последний раз редактировалось VladislavS Пт окт 26, 2018 11:11:35, всего редактировалось 1 раз.
Грызет канифоль
Сообщения: 291
Зарегистрирован: Чт ноя 06, 2014 13:09:06

Сообщение viiv »

[uquote="VladislavS",url="/forum/viewtopic.php?p=3491695#p3491695"]Входящий ток. Например, если ты светодиод анодом на плюс, а катодом на ножку контроллера. Подал "0" и можешь 5 мА на землю брякнуть.[/uquote]
То, что ты описал, это называется "Output Current Sink"
СпойлерИзображение
"injection current" возникает когда ножка оказывается под потенциалом выше питания (или ниже земли)
Собутыльник Кота
Аватара пользователя
Сообщения: 2567
Зарегистрирован: Вт май 01, 2018 19:44:47

Сообщение VladislavS »

Согласен, проще это сформулировать как ток через защитный диод.
Ответить

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