Что предлагаете взамен gcc-arm-none-eabi-9-2020-q2?VladislavS писал(а):Выкиньте компилятор, который на это выражение код генерит
STM32 новичку в ARM что к чему
- Сообщения: 6457
- Зарегистрирован: Пт сен 13, 2013 13:11:31
- Реклама
- Сообщения: 2567
- Зарегистрирован: Вт май 01, 2018 19:44:47
[uquote="Мурик",url="/forum/viewtopic.php?p=3896635#p3896635"]
[/uquote]Тогда научитесь им пользоваться. А скорее всего, правильно читать листинги. Вот добавление этого выражения не добавило ни одного байта к прошивке.
[uquote="Мурик",url="/forum/viewtopic.php?p=3896635#p3896635"]Думаете компилятор кейла лучше будет?
[/uquote]Прыгать с компилятора на компилятор сейчас особого смысла нет. Лучше хорошо уметь пользоваться каким-то одним и дружить с остальными.
- Сообщения: 6457
- Зарегистрирован: Пт сен 13, 2013 13:11:31
[uquote="VladislavS",url="/forum/viewtopic.php?p=3896957#p3896957"]Прыгать с компилятора на компилятор сейчас особого смысла нет.[/uquote]
Прыгать может и нет, а проверить, как проект собирается разными компиляторами, полезно.
Прыгать может и нет, а проверить, как проект собирается разными компиляторами, полезно.
Кстати, насчёт разных компиляторов...
Прикупил такую плату с камерой и дисплеев для экспериментов. Товарищи китайцы даже на github для неё разные Examples держат.
Что плохо - проекты делались под Keil uVision. Попытался их проект для "куба" в вариант под GCC/Makefile переделать, пробросил недостающие DEFINEs (из xml-ки проекта uVision), пути к includes/sources. Проект компилируется. Но:
- с GCC версий 8 или выше - дисплей не инициализируется, шум на нём. Беру GCC 7 или младше - работает (пример 03-LCD_Test)
- с GCC любой версии пока не удалось запустить камеру (пример 08-DCMI2LCD). Сильно не копал, но видно, что вроде как коллбэки от камеры не приходят, код висит в ожидании флага о наличии нового фрейма.
Если прошивать их hex-ы с github (сделанные в uVision), проекты работают.
В общем, совместимость там та ещё...
Прикупил такую плату с камерой и дисплеев для экспериментов. Товарищи китайцы даже на github для неё разные Examples держат.
Что плохо - проекты делались под Keil uVision. Попытался их проект для "куба" в вариант под GCC/Makefile переделать, пробросил недостающие DEFINEs (из xml-ки проекта uVision), пути к includes/sources. Проект компилируется. Но:
- с GCC версий 8 или выше - дисплей не инициализируется, шум на нём. Беру GCC 7 или младше - работает (пример 03-LCD_Test)
- с GCC любой версии пока не удалось запустить камеру (пример 08-DCMI2LCD). Сильно не копал, но видно, что вроде как коллбэки от камеры не приходят, код висит в ожидании флага о наличии нового фрейма.
Если прошивать их hex-ы с github (сделанные в uVision), проекты работают.
В общем, совместимость там та ещё...
- Сообщения: 6457
- Зарегистрирован: Пт сен 13, 2013 13:11:31
А с какими параметрами оптимизации проект собирался под "GCC 8 или выше" ?
- Реклама
-Og во всех случаях. Пытался отключать вообще, но эффекта не было.
Ещё пытался сделать следующего "Франкенштейна":
- Собрал 7-м gcc работающую прошивку, сохранил из сборки сгенерённый объектник lcd.o, почистил проект
- Собрал 8-м gcc неработающую прошивку.
- Заменил объектник lcd.o сохранённым, перелинковал
В таком сочетании заработало. То есть, проблема либо в коде lcd.c, либо в возможно встраивающихся в него функциях из других файлов (хотя lto не включен, так что вряд ли).
P.S. Если интересно покопать, положил свои эксперименты сюда. Там в архиве есть каталоги с продуктами сборки от обеих версий gcc, логи сборки из консоли. Возможно, что-то полезное дало бы сличение файлов lcd.lst в обоих случаях, но "я уже в пижаме"...
Ещё пытался сделать следующего "Франкенштейна":
- Собрал 7-м gcc работающую прошивку, сохранил из сборки сгенерённый объектник lcd.o, почистил проект
- Собрал 8-м gcc неработающую прошивку.
- Заменил объектник lcd.o сохранённым, перелинковал
В таком сочетании заработало. То есть, проблема либо в коде lcd.c, либо в возможно встраивающихся в него функциях из других файлов (хотя lto не включен, так что вряд ли).
P.S. Если интересно покопать, положил свои эксперименты сюда. Там в архиве есть каталоги с продуктами сборки от обеих версий gcc, логи сборки из консоли. Возможно, что-то полезное дало бы сличение файлов lcd.lst в обоих случаях, но "я уже в пижаме"...
- Сообщения: 6457
- Зарегистрирован: Пт сен 13, 2013 13:11:31
-Og -- это все равно оптимизация и в таких ситуациях лучше запретить вовсе. Следующий шаг -- максимальные варнинги. Я любопытства ради загнал в кейл и там полезли разные вырвиглазные, по мнению компиля, шедевры, типа такого:
Оно вроде и законно, но лучше просмотреть такие места попристальнее.
Код: Выделить всё
void LCD_ShowChar(uint16_t x,uint16_t y,uint8_t num,uint8_t size,uint8_t mode)
{
...
uint16_t write[size][size==12?6:8];
...
ST7735_FillRGBRect(&st7735_pObj,x0,y0,(uint8_t *)&write,size==12?6:8,size);
...
Меня сильно смущает ещё одна вещь. Берём практически любую функцию в LCD.c, например, lcd_senddata
https://github.com/WeActTC/MiniSTM32H7x ... lcd.c#L312
Это что же, деление нуля на нуль получается? В случае, если HAL-овская функция ОК вернёт?
https://github.com/WeActTC/MiniSTM32H7x ... lcd.c#L312
Код: Выделить всё
result =HAL_SPI_Transmit(SPI_Drv,pdata,length,100);
LCD_CS_SET;
result /= -result;- Сообщения: 2516
- Зарегистрирован: Пт июл 12, 2019 22:52:01
Правильно ли я понимаю вот это выражение:
#define RTC ((RTC_TypeDef *) RTC_BASE)
Здесь создается указатель RTC_BASE типа структуры RTC_TypeDef и сразу же объявляется для него новое имя попроще RTC?
А здесь:
#define RTC_BASE (APB1PERIPH_BASE + 0x2800)
Указывается, что есть некоторый адрес, который принадлежит шине АРВ1 плюс смещение к нему, получается адрес начала регистров RTC в памяти. И объявляется это все для простоты под одним именем RTC_BASE?
После все этого, т.к. структура была объявлена через ТейпДеф, я могу использовать оператор (->), так и оператор (.)?
#define RTC ((RTC_TypeDef *) RTC_BASE)
Здесь создается указатель RTC_BASE типа структуры RTC_TypeDef и сразу же объявляется для него новое имя попроще RTC?
А здесь:
#define RTC_BASE (APB1PERIPH_BASE + 0x2800)
Указывается, что есть некоторый адрес, который принадлежит шине АРВ1 плюс смещение к нему, получается адрес начала регистров RTC в памяти. И объявляется это все для простоты под одним именем RTC_BASE?
После все этого, т.к. структура была объявлена через ТейпДеф, я могу использовать оператор (->), так и оператор (.)?
Станислав
- Сообщения: 2567
- Зарегистрирован: Вт май 01, 2018 19:44:47
Всё так, кроме того, что никаких указателей не создаётся. Препроцессор тупо каждый раз вместо RCC будет подставлять эту абракадабру.
Точно! Это же директивы препроцессора... А не объявления переменных
Добавлено after 7 minutes 10 seconds:
Мне потихоньку начинает казаться, что я уже на грани просветления фундамента по работе с этими микроконтроллерами... Все мои проблемы только с языком Си.
Добавлено after 1 minute 56 seconds:
По сути, если разобраться с тем, что написано в этом заголовочном файле и как это работает, больше вопросов и не останется, кроме некоторых нюансов в Рефренс Мануале.
Добавлено after 7 minutes 10 seconds:
Мне потихоньку начинает казаться, что я уже на грани просветления фундамента по работе с этими микроконтроллерами... Все мои проблемы только с языком Си.
Добавлено after 1 minute 56 seconds:
По сути, если разобраться с тем, что написано в этом заголовочном файле и как это работает, больше вопросов и не останется, кроме некоторых нюансов в Рефренс Мануале.
Станислав
Понимаю, что можно все и проверить в железе... Но спросить все равно гложит...
Правильно ли я настроил тактирование от внешнего кварца 8 МГц, чтобы с ФАПЧ получилось 72 МГц? Или я где-то чего-то не учел и накосячил?
З.Ы. Есть небольшие непонятки с флешем. А также с последними двумя строками, можно ли их в одну записать?
Правильно ли я настроил тактирование от внешнего кварца 8 МГц, чтобы с ФАПЧ получилось 72 МГц? Или я где-то чего-то не учел и накосячил?
Код: Выделить всё
FLASH->ACR |= (FLASH_ACR_PRFTBE | FLASH_ACR_LATENCY_1); // Сразу включаем задержку для Флеша, т.к. на больших частотах ему плохо работать
RCC->CR |= RCC_CR_HSEON; // Включаем внешний резонатор 8 МГц
while ((RCC->CR & RCC_CR_HSERDY ) != RCC_CR_HSERDY) // Ждем запуска резонатора
{
}
RCC->CFGR |= (RCC_CFGR_PLLMULL_2 | RCC_CFGR_PLLMULL_1 | RCC_CFGR_PLLMULL_0 | RCC_CFGR_PLLSRC); // Настраиваем PLL (умножить на 9) и включаем тактирование PLL от HSE
RCC->CR |= RCC_CR_PLLON; // Включаем сам PLL
while ((RCC->CR & RCC_CR_PLLRDY) != RCC_CR_PLLRDY) // Ждем готовности PLL
{
}
RCC->CFGR |= RCC_CFGR_PPRE1_DIV2; // Включаем делитель PLL на 2 для шины АВР1, т.к. она не более 32 МГц
RCC->CFGR |= RCC_CFGR_SW_PLL; // Включаем тактирование всего в системе!
Станислав
- Сообщения: 2567
- Зарегистрирован: Вт май 01, 2018 19:44:47
Код: Выделить всё
// Настройка FLASH
FLASH->ACR = FLASH_ACR_PRFTBE | _VAL2FLD(FLASH_ACR_LATENCY, 2);
RCC->CR = _VAL2FLD(RCC_CR_HSITRIM, 16)
| RCC_CR_HSION
| RCC_CR_HSEON; //Включаем HSE
while(!(RCC->CR & RCC_CR_HSERDY)); //Ждём пока запустится HSE
//Задаём источники тактирования и прескалеры
// SYSCLK = 72 МГц, USB = 48 МГц,
// PCLK1 = 36 МГц, PCLK2 = 72 МГц,
// ADC = 12 МГц
RCC->CFGR = RCC_CFGR_MCO_NOCLOCK
| RCC_CFGR_USBPRE_1d5
| RCC_CFGR_PLLMULL9
| RCC_CFGR_PLLSRC_HSE
| RCC_CFGR_ADCPRE_DIV6
//| RCC_CFGR_PLLXTPRE // Раскомментировать для кварца 16 МГц
| RCC_CFGR_PPRE2_DIV1
| RCC_CFGR_PPRE1_DIV2
| RCC_CFGR_HPRE_DIV1
| RCC_CFGR_SW_HSE;
RCC->CR = _VAL2FLD(RCC_CR_HSITRIM, 16)
| RCC_CR_HSEON
| RCC_CR_PLLON; // Включаем PLL, выключаем HSI
while(!(RCC->CR & RCC_CR_PLLRDY)); // Ждём пока запустится PLL
//Переключаемся на PLL с установленнными ранее прескалерами
RCC->CFGR = RCC_CFGR_MCO_NOCLOCK
| RCC_CFGR_USBPRE_1d5
| RCC_CFGR_PLLMULL9
| RCC_CFGR_PLLSRC_HSE
| RCC_CFGR_ADCPRE_DIV6
//| RCC_CFGR_PLLXTPRE // Раскомментировать для кварца 16 МГц
| RCC_CFGR_PPRE2_DIV1
| RCC_CFGR_PPRE1_DIV2
| RCC_CFGR_HPRE_DIV1
| RCC_CFGR_SW_PLL;
А откуда вы взяли вот такие конструкции?
_VAL2FLD(FLASH_ACR_LATENCY, 2
И если я пока не использую ЮСБ и АЦП, мне их все равно надо настраивать?
Добавлено after 1 minute 15 seconds:
И похоже, я зря везде понаписал |=
Добавлено after 8 minutes 48 seconds:
дА, и HSI я не выключил... Или это не обязательно?
_VAL2FLD(FLASH_ACR_LATENCY, 2
И если я пока не использую ЮСБ и АЦП, мне их все равно надо настраивать?
Добавлено after 1 minute 15 seconds:
И похоже, я зря везде понаписал |=
Добавлено after 8 minutes 48 seconds:
дА, и HSI я не выключил... Или это не обязательно?
Станислав
- Сообщения: 7080
- Зарегистрирован: Сб янв 28, 2006 22:47:24
Он только в целях снижения потребления отключается. Если не отключать все работает точно так же.
Астролябия-сама меряет, было бы что мерять!!!
Понял. Лучше отключить.
А верхние конструкции? и почему у меня работает также запущенный RTC, где я тоже писал |=, а не просто =?
Добавлено after 14 minutes 52 seconds:
Кстати, я не включил CSS... Тоже надо доделать.
А если я выключу HSI и в случае сбоя HSE сам CSS включит его или нет?
А верхние конструкции? и почему у меня работает также запущенный RTC, где я тоже писал |=, а не просто =?
Добавлено after 14 minutes 52 seconds:
Кстати, я не включил CSS... Тоже надо доделать.
А если я выключу HSI и в случае сбоя HSE сам CSS включит его или нет?
Станислав
|= это чтение-модификация-присвоение
= прямое присвоение
Использование каждого из вариантов зависит от ситуации.
Есть еще такая разновидность 1-го варианта:
Это если нужно обнулить биты масок 1 и 2, а биты масок 3 и 4 выставить.
Добавлено after 9 minutes 35 seconds:
Кстати, хорошо бы "ожидание запуска резонатора" снабдить тайм-аут таймером, чтобы программа не зависла на while в случае проблем с кварцем.
После этого проверить tot на 0. Если 0, значит HSE не запустился, переходим к плану Б.
= прямое присвоение
Использование каждого из вариантов зависит от ситуации.
Есть еще такая разновидность 1-го варианта:
Код: Выделить всё
REGISTER = (REGISTER & ~(MASK_1 | MASK_2)) | (MASK_3 | MASK_4);Добавлено after 9 minutes 35 seconds:
Кстати, хорошо бы "ожидание запуска резонатора" снабдить тайм-аут таймером, чтобы программа не зависла на while в случае проблем с кварцем.
Код: Выделить всё
unsigned short tot = 5000; // при необходимости увеличить
while (((RCC->CR & RCC_CR_HSERDY) == 0) && (--tot)); // Ждем запуска резонатора
Каждый имеет право на свое личное ошибочное мнение.
У меня было тяжелое детство - я до 14 лет смотрел черно-белый телевизор.
У меня было тяжелое детство - я до 14 лет смотрел черно-белый телевизор.
- Сообщения: 2567
- Зарегистрирован: Вт май 01, 2018 19:44:47
[uquote="Zhuk72",url="/forum/viewtopic.php?p=3898341#p3898341"][/uquote]Только не unsigned short, а uint32_t. Вы же на 32-битном проце работаете, 16-битная переменная даст лишний код.
Код: Выделить всё
unsigned short tot = 5000; // при необходимости увеличить
Последний раз редактировалось VladislavS Вс сен 27, 2020 15:44:20, всего редактировалось 1 раз.
Так биты, которые обозначены в хидере, они уже сами нужные единички? Их можно просто присваивать? Или все же лучше как маску накладывать? Просто везде вроде их через |= используют...
И по поводу АЦП и ЮСБ, тоже надо сразу частоты на них выставлять?
И по поводу АЦП и ЮСБ, тоже надо сразу частоты на них выставлять?
Станислав


