|
|
  |
Оптимизация в Keil |
|
|
|
Jul 23 2015, 09:45
|
практикующий тех. волшебник
    
Группа: Участник
Сообщений: 1 190
Регистрация: 9-09-05
Пользователь №: 8 417

|
Цитата(Arlleex @ Jul 22 2015, 21:56)  ...в смысле изменялся асм на выходе компилятора? Ты имеешь в виду машинный код? Или прошедший оптимизацию входной асм? после отработки компилятора на выходе получаем файлы с коментнутыми текстовыми инструкциями и машинный код вот там видно пропадание нескольких команд. причём параметры среды одни и те-жи. исходник менялся незначительно - ну типа нопов дополнительных и уже эффект проявлялся. Никакой оптимизацией это не объяснить. Чистый глюкало компилятора. Да, и ощущение что именно от больших размеров компилируемой программы зависит. Т.е. это один раз всего было явно поймано за руку. Кода в то время писал разное(под 51) на мелких замечено не было. только в одном проекте такое проявилось. Сначала как баг, который я не мог понять природу. Далее методом контрольных точек было найден логический блок, ну и при дальнейшем скурпулёзном просмотре кода выявило конкретное место и отсутствие команд. после научного метода тыка повлиять на ситуацию - была найдена закономерность. где то так. давно было дело...
|
|
|
|
|
Feb 5 2016, 12:44
|
Группа: Участник
Сообщений: 8
Регистрация: 2-07-15
Пользователь №: 87 377

|
Добрый день! Не стал создавать новую тему. Вопрос по уровням оптимизации в Keil 5.14. Предыстория такая. Скачал библиотеку USB с сайта st.com (STSW-STM32092 STM32F0x2xx USB FS device library (UM1717)). Запустил проект виртуального ком порта. Убрал из кода файлы отладочной платы, поменял камень на STM32F042K6. Убрал USART. Сделал так, чтобы все что принимается с USB выплёвывалось туда же. Все работает отлично, определятся на компе, как вирт ком порт, шлю данные из терминала и получаю их же. В проекте стоит уровень оптимизации 3 (Level 3 (-O3)) по умолчанию. Если выставить уровень оптимизации 0 (Level 0 (-O0)), то при попытке отправить данные из консоли в контроллер, сваливается в hardfault на 8-й строчке. При всех других уровнях оптимизации все работает (Level 1 (-O1), Level 2 (-O2)). Код void PMAToUserBufferCopy(uint8_t *pbUsrBuf, uint16_t wPMABufAddr, uint16_t wNBytes) { uint32_t n = (wNBytes + 1) >> 1; uint32_t i; uint16_t *pdwVal; pdwVal = (uint16_t *)(wPMABufAddr + PMAAddr); for (i = n; i != 0; i--) { *(uint16_t*)pbUsrBuf++ = *pdwVal++; // Тут падает pbUsrBuf++; } } Я бы всё понял, если бы было всё наоборот. Как мне кажется, все указатели и массивы нормально объявлены, в противном случае падало бы на всех уровнях оптимизации. Может есть нормальное описание уровней оптимизации keil'а? Или мысли по этому поводу? Или может быть, кто-нибудь сможет объяснить "на пальцах" как работает оптимизация в keil?
|
|
|
|
|
Feb 5 2016, 13:15
|
Гуру
     
Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136

|
Цитата(Booger @ Feb 5 2016, 15:44)  Может есть нормальное описание уровней оптимизации keil'а? Какой смысл разбираться в деталях оптимизации? Тут ведь как: либо а) в коде ошибка, либо б) баг в компиляторе. Совершенно очевидно, что вариант а) в 100500 раз вероятнее. Цитата(Booger @ Feb 5 2016, 15:44)  Или мысли по этому поводу? Мысли есть, конечно. Заняться старой доброй отладкой. Вытащить из регистров причину Hard Fault. Ну и разбираться дальше.
|
|
|
|
|
Feb 7 2016, 06:42
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
QUOTE (ViKo @ Feb 7 2016, 07:58)  Я считаю, что работоспособность программы при любых уровнях оптимизации и есть тот тест, который отличает хороший код от сами_знаете_какого. Именно так. Более того, абсолютно всегда следует с самого начала использовать максимальные уровни оптимизации И НИКОГДА НЕ ОТКЛЮЧАТЬ, единственно, что в процессе работы можно, при жесткой необходимости сдвигать оптимизацию по скорости больше к оптимизации по размеру. Да и то, делать это не глобально, а для отдельных обьектов компиляции - каждому свое. Даже если при работе со сразу реальной оптимизацией наступить, вдруг (уже много много лет для свежих компиляторов не наступал) на непонимание Вами написанного компилятором, то это легче локализовать и скоректировать в процессе написания в момент проявления проблемы и не постфактум.
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Feb 7 2016, 08:38
|

Универсальный солдатик
     
Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362

|
Цитата(zltigo @ Feb 7 2016, 09:42)  Именно так. Более того, абсолютно всегда следует с самого начала использовать максимальные уровни оптимизации И НИКОГДА НЕ ОТКЛЮЧАТЬ, единственно, что в процессе работы можно, при жесткой необходимости сдвигать оптимизацию по скорости больше к оптимизации по размеру. Да и то, делать это не глобально, а для отдельных обьектов компиляции - каждому свое. Даже если при работе со сразу реальной оптимизацией наступить, вдруг (уже много много лет для свежих компиляторов не наступал) на непонимание Вами написанного компилятором, то это легче локализовать и скоректировать в процессе написания в момент проявления проблемы и не постфактум. Иногда включаю -O0, чтобы определить, правильно ли понял меня компилятор.  При этом уровне гораздо легче разбираться по ассемблерным командам. В Кейле задал 2 Target - Debug и Release - с уровнями -O0 и -O3, и когда не работает, легким движением мыши переключаюсь на Debug.
|
|
|
|
|
Feb 7 2016, 09:37
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
QUOTE (ViKo @ Feb 7 2016, 10:38)  Иногда включаю -O0, чтобы определить, правильно ли понял меня компилятор. При этом уровне гораздо легче разбираться по ассемблерным командам. Понял/не понял, это по результату смотрится. И если не понял, то прежде всего надо смотреть Вы сами-то себя поняли, когда писали? Чего уж тут в ассемблерные команды лезть - сишный текст по любому читается легче. Нежели Вы поняли, что хотели и написали, то компиляторы современные тоже поймут. QUOTE Debug и Release - с уровнями -O0 и -O3 Кроме этих "готовых рецептов" есть еще масса ключиков.
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Feb 8 2016, 04:14
|
Группа: Участник
Сообщений: 8
Регистрация: 2-07-15
Пользователь №: 87 377

|
В том то и дело, товарищи! Работает на всех уровнях оптимизации, кроме Leavel - 0 (O0). Я бы даже не сувался на форум, если было бы наоборот. При Leavel - 3 (O3) неудобно пользоваться "дебагером". Остальными уровнями (Leavel - 1 (O1) и Leavel - 2 (O2)) еще ни разу не пользовался. С одной стороны, конечно же хорошо, что всё отлично работает на 3-м уровне оптимизации, как все мы и добиваемся в конечном итоге, но хотелось бы докопаться до истины. Пока в голову ничего не пришло, как начать переписывать USB-шный пример, а может быть придется и всю библиотеку.
ViKo, RabidRabbit, спасибо, буду смотреть.
Сообщение отредактировал Booger - Feb 8 2016, 04:17
|
|
|
|
|
Feb 8 2016, 05:44
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Смею предположить, что с включенной оптимизацией компилятор заменяет этот цикл на memcpy(), которая, в отличие от этого кода, корректно работает с невыровненными данными. При отключенной оптимизации, в зависимости от расположения pbUsrBuf, этот код может приводить к невыровненному доступу, который ядро M0 не поддерживает. За столько времени можно было эту маленькую функцию пройти в окне дизассемблера на любом уровне оптимизации, найти вызывающую падение ассемблерную команду и понять, откуда у нее берутся неправильные аргументы.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Feb 9 2016, 05:30
|
Группа: Участник
Сообщений: 8
Регистрация: 2-07-15
Пользователь №: 87 377

|
Спасибо всем за помощь!
Действительно, если использовать memcpy, то работает и на 0-м уровне оптимизации.
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|