STM32 новичку в ARM что к чему
ОК, спасибо.
Кто мешает тебе выдумать порох непромокаемый? (К. Прутков, мысль № 133)
- Реклама
- Сообщения: 6457
- Зарегистрирован: Пт сен 13, 2013 13:11:31
На хабре появилась статеечка, как ручками через регистры сконфигурировать тактирование на STM32H7. Никогда ранее с седьмой серией не сталкивался, но что и зачем делает автор в общих чертах понятно. Кроме одного момента:
Занесение значения в регистр RCC_PLLCKSELR зачем-то разбито аж на шесть шагов. Никто не в курсе, зачем все это и почему нельзя было написать просто
?
Код: Выделить всё
//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_DIVM1_2;Видимо, потому что такой "сложный" способ не затрагивает остальные биты регистра RCC->PLLCKSELR. В отличие от "простого", обнуляющего их.
- Сообщения: 6457
- Зарегистрирован: Пт сен 13, 2013 13:11:31
Да фиг с ними, с остальными. Я про то, что при первоначальной инициализации можно все эти "остальные" загонять в регистр одним присваиванием. Какой смысл перещелкивать битики по одному в то время, когда PLL даже не включен, а само состояние этих битиков известно? Автор, судя по его статьям на хабре, не похож на неофита, но то, что он делает я объяснить себе не могу. По моим представлениям -- это полная бессмыслица.
- Сообщения: 2567
- Зарегистрирован: Вт май 01, 2018 19:44:47
Мне попадалась следующая аргументация:
- мне так понятнее/удобнее/красивее;
- ты что память экономишь? Там её хоть опой кушай;
- опять ты со своим "=", пиши как хочешь.
А в твоём примере даже не на 6 шагов, а на 18 разбито! 6*(чтение, логическая операция, запись).
Давай в ассемблерных командах посчитаем:
- загрузка адреса регистра 1 шт.
- чтение регистра 6 шт.
- загрузка константы 6 шт.
- логическая операция 6 шт.
- запись регистра 6 шт.
ИТОГО: 25 команд.
Если откинуть команду загрузки адреса регистра, так как в предыдущих командах мы наверняка с RCC уже работали (включали HSE наверняка), то соотношение получается 24:2. В 12 раз, Карл!
- мне так понятнее/удобнее/красивее;
- ты что память экономишь? Там её хоть опой кушай;
- опять ты со своим "=", пиши как хочешь.
А в твоём примере даже не на 6 шагов, а на 18 разбито! 6*(чтение, логическая операция, запись).
Давай в ассемблерных командах посчитаем:
- загрузка адреса регистра 1 шт.
- чтение регистра 6 шт.
- загрузка константы 6 шт.
- логическая операция 6 шт.
- запись регистра 6 шт.
ИТОГО: 25 команд.
Если откинуть команду загрузки адреса регистра, так как в предыдущих командах мы наверняка с RCC уже работали (включали HSE наверняка), то соотношение получается 24:2. В 12 раз, Карл!
Последний раз редактировалось VladislavS Пт окт 26, 2018 06:58:20, всего редактировалось 1 раз.
- Реклама
На самом деле, работать с битами регистра не затрагивая остальные - это достаточно важный принцип. Хотя, если речь идёт об изначальной "только один раз" инициализации на старте, можно и попроще.
Хотя я бы данный код расписал бы скорее так
Не знаю, существует ли такая маска в CMSIS макросах. Если нет - сделал бы свою.
Хотя я бы данный код расписал бы скорее так
Код: Выделить всё
RCC->PLLCKSELR &= ~(RCC_PLLCKSELR_DVMI1_MASK);
RCC->PLLCKSELR |= RCC_PLLCKSELR_DIVM1_2;- Сообщения: 2567
- Зарегистрирован: Вт май 01, 2018 19:44:47
Ещё один.
Боишься биты попортить - напиши так
Потому что запись промежуточного состояния с занулеными битами в общем случае может дать побочный эффект.
Код: Выделить всё
RCC->PLLCKSELR = (RCC->PLLCKSELR & ~RCC_PLLCKSELR_DVMI1_MASK) | RCC_PLLCKSELR_DIVM1_2; И в чём принципиальное отличие от моего варианта, кроме того, что здесь это в виде одной длинной строки?
- Сообщения: 3604
- Зарегистрирован: Пн июл 28, 2008 22:12:01
[uquote="a5021",url="/forum/viewtopic.php?p=3491273#p3491273"]Занесение значения в регистр RCC_PLLCKSELR зачем-то разбито аж на шесть шагов. Никто не в курсе, зачем все это и почему нельзя было написать просто
?[/uquote]
Тяжелое наследие 8ми биток.
Код: Выделить всё
RCC -> PLLCKSELR = RCC_PLLCKSELR_DIVM1_2;Тяжелое наследие 8ми биток.
- Сообщения: 32
- Зарегистрирован: Вс ноя 13, 2016 18:04:13
Ребята, скажите такой вопрос. В РМ на 103 контроллер есть таблица электрических параметров. Что такое инжектированный ток injected current?
- Вложения
-
- вопрос.pdf
- current haracteristics
- (364.81 КБ) 260 скачиваний
- Сообщения: 6457
- Зарегистрирован: Пт сен 13, 2013 13:11:31
[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
[uquote="WiseLord",url="/forum/viewtopic.php?p=3491563#p3491563"]И в чём принципиальное отличие от моего варианта, кроме того, что здесь это в виде одной длинной строки?[/uquote]Вы правда не видите разницу между "=" и последовательными "&=" и "|=" ?
Принципиальной - не вижу. Это не критичный к скорости участок кода, выполняется только один раз. Ну, будет read-modify-write дважды выполнен, а не один раз.. что с того? Читабельность кода зато отличается.
- Сообщения: 2567
- Зарегистрирован: Вт май 01, 2018 19:44:47
[uquote="AlDr70",url="/forum/viewtopic.php?p=3491661#p3491661"]Ребята, скажите такой вопрос. В РМ на 103 контроллер есть таблица электрических параметров. Что такое инжектированный ток injected current?[/uquote]
Входящий ток. Например, если ты светодиод анодом на плюс, а катодом на ножку контроллера. Подал "0" и можешь 5 мА на землю брякнуть.
Входящий ток. Например, если ты светодиод анодом на плюс, а катодом на ножку контроллера. Подал "0" и можешь 5 мА на землю брякнуть.
- Сообщения: 6457
- Зарегистрирован: Пт сен 13, 2013 13:11:31
[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
А я бы вот так написал
а ещё лучше вообще определить _RCC_PLLCKSELR_DIVM1() и вот так
Код: Выделить всё
RCC->PLLCKSELR = RCC_PLLCKSELR_PLLSRC_HSE | _VAL2FLD(RCC_PLLCKSELR_DIVM1,4) | _VAL2FLD(RCC_PLLCKSELR_DIVM2,32) | _VAL2FLD(RCC_PLLCKSELR_DIVM3,32);Код: Выделить всё
RCC->PLLCKSELR = RCC_PLLCKSELR_PLLSRC_HSE | _RCC_PLLCKSELR_DIVM1(4) | _RCC_PLLCKSELR_DIVM2(32) | _RCC_PLLCKSELR_DIVM3(32);- Сообщения: 6457
- Зарегистрирован: Пт сен 13, 2013 13:11:31
- Сообщения: 2567
- Зарегистрирован: Вт май 01, 2018 19:44:47
Это не магические числа, а реальные коэффициенты деления. Можно подумать, задавая поразрядно эти магические числа ты много меняешь. В случае, если это не реальные коэффициенты, а магические числа, то конечно надо их задефайнить в реальные.
Вот, например, от 411-го.Никакие это не магические числа, а Q=4, N=96 и M=4. Куда уж понятней? Нафига их поразрядно задавать?
Вот, например, от 411-го.
Код: Выделить всё
RCC->PLLCFGR = _RCC_PLLCFGR_PLLQ(4) | RCC_PLLCFGR_PLLSRC_HSE | RCC_PLLCFGR_PLLP_div2 | _RCC_PLLCFGR_PLLN(96) | _RCC_PLLCFGR_PLLM(4);
Последний раз редактировалось VladislavS Пт окт 26, 2018 11:11:35, всего редактировалось 1 раз.
- Сообщения: 291
- Зарегистрирован: Чт ноя 06, 2014 13:09:06
[uquote="VladislavS",url="/forum/viewtopic.php?p=3491695#p3491695"]Входящий ток. Например, если ты светодиод анодом на плюс, а катодом на ножку контроллера. Подал "0" и можешь 5 мА на землю брякнуть.[/uquote]
То, что ты описал, это называется "Output Current Sink"
"injection current" возникает когда ножка оказывается под потенциалом выше питания (или ниже земли)
То, что ты описал, это называется "Output Current Sink"
Спойлер
- Сообщения: 2567
- Зарегистрирован: Вт май 01, 2018 19:44:47


