реклама на сайте
подробности

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> Разное поведение в отладчике и без него.
tdi@013h
сообщение Apr 28 2012, 14:29
Сообщение #1


Участник
*

Группа: Участник
Сообщений: 17
Регистрация: 8-02-11
Пользователь №: 62 795



Дано: KEIL, плата на stm32f103rb, ULINK2.
Задача: поморгать диодами.
Код:
Код
int main(void)
{
    InitHardware();
    for (;;)
    {
        GPIO_ResetBits(Led_1);
        Wait(25000);
        GPIO_ResetBits(Led_2);
        Wait(25000);
        GPIO_SetBits(Led_1);
        Wait(25000);
        GPIO_SetBits(Led_2);
        Wait(25000);
    }
}

Код
void Wait(int Count)
{
    for(; Count !=0; Count--);
}


Когда расставляю брэйкпоинты по телу фона и хожу в отладчике по шагам, то все моргает в нужной последовательности.
Когда отключаю дебаггер, делаю ресет и запускаю, то оба диода просто горят.
Что я делаю не так? И почему так происходит?
Go to the top of the page
 
+Quote Post
mdmitry
сообщение Apr 28 2012, 14:53
Сообщение #2


Начинающий профессионал
*****

Группа: Свой
Сообщений: 1 215
Регистрация: 25-10-06
Из: СПб
Пользователь №: 21 648



Цитата(tdi@013h @ Apr 28 2012, 18:29) *
Код
void Wait(int Count)
{
    for(; Count !=0; Count--);
}

Как Вы думаете, сколько времени выполняется эта функция? У Вас 25000 циклов выполняется при тактовой в МГц. Сделайте задержки большими и лучше штатными средствами типа delay. Посмотрите библиотеку к вашему компилятору.


--------------------
Наука изощряет ум; ученье вострит память. Козьма Прутков
Go to the top of the page
 
+Quote Post
scifi
сообщение Apr 28 2012, 14:57
Сообщение #3


Гуру
******

Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136



Цитата(tdi@013h @ Apr 28 2012, 18:29) *
Когда отключаю дебаггер, делаю ресет и запускаю, то оба диода просто горят.

Действительно забавно. Они моргают, только быстро-быстро :-)
Точные задержки нужно к аппаратным таймерам привязывать. Компилятор может просто выкинуть ваш цикл ожидания и будет прав.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Apr 29 2012, 17:03
Сообщение #4


Гуру
******

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



QUOTE (scifi @ Apr 28 2012, 17:57) *
Компилятор может просто выкинуть ваш цикл ожидания и будет прав.
99.99%, что он именно так и сделал. Чтобы этого избежать, можно объявить Count как volatile.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
tdi@013h
сообщение Apr 30 2012, 02:09
Сообщение #5


Участник
*

Группа: Участник
Сообщений: 17
Регистрация: 8-02-11
Пользователь №: 62 795



Цитата(mdmitry @ Apr 28 2012, 17:53) *
Как Вы думаете, сколько времени выполняется эта функция? У Вас 25000 циклов выполняется при тактовой в МГц. Сделайте задержки большими и лучше штатными средствами типа delay. Посмотрите библиотеку к вашему компилятору.

Скопировал 1в1 функцию из примера моргалки к своей плате.

Компилятор проверю, потому как пересаживаюсь из Eclipse и arm-none-eabi-gcc на Keil и его компилятор, там такие фокусы работали.
Общую идею понял, спасибо.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Apr 30 2012, 08:44
Сообщение #6


Гуру
******

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



QUOTE (tdi@013h @ Apr 30 2012, 05:09) *
пересаживаюсь из Eclipse и arm-none-eabi-gcc на Keil и его компилятор, там такие фокусы работали.
Только при отключении оптимизации (-O0).


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
toweroff
сообщение Apr 30 2012, 19:16
Сообщение #7


Гуру
******

Группа: Свой
Сообщений: 2 957
Регистрация: 19-09-06
Из: Москва
Пользователь №: 20 514



задержки а-ля
for(i=0;i<NEED_SIZE;i++)
в отдельно взятой функции проходили и здесь жевали уже. Все верно, либо оптимизацию в 0, либо volatile
+1 в общем sm.gif
Go to the top of the page
 
+Quote Post
ViKo
сообщение Apr 30 2012, 20:37
Сообщение #8


Универсальный солдатик
******

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



У меня в Keil задержки в виде
#define Delay(TIME) for (uint32 i=(72000000/4*TIME); i ; i--)
не оптимизировались до выбрасывания никогда.

А у топикстартера частота моргания диодов порядка 180 Гц. Нужно иметь слишком зоркий глаз... соколиный sm.gif
Go to the top of the page
 
+Quote Post
Dog Pawlowa
сообщение May 1 2012, 01:50
Сообщение #9


Гуру
******

Группа: Свой
Сообщений: 2 702
Регистрация: 14-07-06
Пользователь №: 18 823



Цитата(ViKo @ Apr 30 2012, 23:37) *
У меня в Keil задержки не оптимизировались до выбрасывания никогда.

Что свидетельствует о качестве оптимизации хвалёного кайла wink.gif


--------------------
Уходя, оставьте свет...
Go to the top of the page
 
+Quote Post
ViKo
сообщение May 1 2012, 06:25
Сообщение #10


Универсальный солдатик
******

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



Цитата(Dog Pawlowa @ May 1 2012, 04:50) *
Что свидетельствует о качестве оптимизации хвалёного кайла wink.gif

Просто Кайл знает, чего хотят люди, когда пишут такие циклы.

Доводя мысль до абсурда - зачем вообще что-то компилировать, если устройство рано или поздно отключится (сдохнет)?

__nop, кстати, тоже никогда не выбрасывается.
Go to the top of the page
 
+Quote Post
toweroff
сообщение May 1 2012, 15:24
Сообщение #11


Гуру
******

Группа: Свой
Сообщений: 2 957
Регистрация: 19-09-06
Из: Москва
Пользователь №: 20 514



Цитата(Dog Pawlowa @ May 1 2012, 05:50) *
Что свидетельствует о качестве оптимизации хвалёного кайла wink.gif

так вроде ж это инструменты самого ARM, или я не прав?
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение May 1 2012, 18:29
Сообщение #12


Гуру
******

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



QUOTE (ViKo @ May 1 2012, 09:25) *
Просто Кайл знает, чего хотят люди, когда пишут такие циклы.
Телепатически узнает?
QUOTE (ViKo @ May 1 2012, 09:25) *
__nop, кстати, тоже никогда не выбрасывается.
Потому что он либо intrinsic-функция, о которой компилятор знает, что она с побочными эффектами, либо это asm volatile вставка.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
aaarrr
сообщение May 1 2012, 20:06
Сообщение #13


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(ViKo @ May 1 2012, 00:37) *
У меня в Keil задержки в виде
#define Delay(TIME) for (uint32 i=(72000000/4*TIME); i ; i--)
не оптимизировались до выбрасывания никогда.

Старые версии RVCT действительно не выбрасывали подобные конструкции. Но в новых такой фокус уже не пройдет.
Go to the top of the page
 
+Quote Post
ViKo
сообщение May 2 2012, 08:19
Сообщение #14


Универсальный солдатик
******

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



Результаты экспериментов с Keil 4.50 следующие.
Цикл вида
#define DELAY(TIME) for (uint32_t i = (24000000 / 4 * TIME); i-- ; )
выбрасывается в Keil в единственном случае - когда выбрана Optimization Level 3 и Optimize for Time. При остальных настройках - остается.
Размер кода для цикла вида
#define DELAY(TIME) for (volatile uint32_t i = (24000000 / 4 * TIME); i-- ; )
при Optimization Level 1, 2, 3 больше, чем без volatile. Но экономить на 4-х байтах смысла нет, поэтому лучше использовать volatile. Ну, и, естественно, такой цикл не выбрасывается.

Так что, Keil - оправдан. sm.gif
Go to the top of the page
 
+Quote Post
ViKo
сообщение May 3 2012, 04:40
Сообщение #15


Универсальный солдатик
******

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



Продолжение экспериментов. Исходный код:
Код
#define DELAY(TIME) for (volatile uint32_t i = (24000000 / 4 * TIME); i--; )
uint32_t cnt;
int32_t main(void)
{
  __nop;
  while (1) {
    cnt++;
    __nop; __nop; __nop;
    DELAY(0.001);
  }
}

Компилируется в следующий, при -O1 (при -O0 появляется одна команда NOP)
Код
;;;94     int32_t main(void)
000000  4a16              LDR      r2,|L1.92|
;;;95     {
;;;96       __nop;
;;;97       while (1) {
;;;98         cnt++;
;;;99         __nop; __nop; __nop;
;;;100        DELAY(0.001);
000002  f2417370          MOV      r3,#0x1770
                  |L1.6|
000006  6810              LDR      r0,[r2,#0]           ;98 ; cnt
000008  1c40              ADDS     r0,r0,#1             ;98
00000a  6010              STR      r0,[r2,#0]           ;98 ; cnt
00000c  4619              MOV      r1,r3
                  |L1.14|
00000e  0008              MOVS     r0,r1
000010  f1a10101          SUB      r1,r1,#1
000014  d1fb              BNE      |L1.14|
000016  e7f6              B        |L1.6|
;;;101      }
;;;102    }

Как!? Как это согласуется с цитатой из помощи:
Цитата
__nop
This intrinsic inserts a NOP instruction or an equivalent code sequence into the instruction stream generated by the compiler. One NOP instruction is generated for each __nop intrinsic in the source.

The compiler does not optimize away the NOP instructions, except for normal unreachable code elimination. The __nop intrinsic also acts as a barrier for instruction scheduling in the compiler. That is, instructions are not moved from one side of the NOP to the other as a result of optimization.
Go to the top of the page
 
+Quote Post

2 страниц V   1 2 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 18th July 2025 - 16:29
Рейтинг@Mail.ru


Страница сгенерированна за 0.01492 секунд с 7
ELECTRONIX ©2004-2016