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

 
 
> WinAVR, _delay_ms(), строки и оптимизация.
Laksus
сообщение Nov 5 2010, 19:17
Сообщение #1


Частый гость
**

Группа: Участник
Сообщений: 146
Регистрация: 16-05-05
Пользователь №: 5 069



Програмка для ATmega32, WinAVR-20100110.
Инициализируется USART для передачи.
После этого хочу отправить через USART несколько групп символов. С паузой между группами в несколько секунд.
Задержки решил сделать через _delay_ms(2000).

Оказалось, что если оптимизация "OPT = s", то правильно передается только последняя строка, а вместо остальных строк передается мусор. Насколько я понял указатель ставится на адрес ноль, а не на адрес строки.
Если отключить оптимизацию ("OPT = 0"), то все строки передаются правильно.

Если вместо _delay_ms() использую самодельную задержку delay_sec(uint8_t T){for..{for..{for..{for..{asm("nop")}}}}},
то все строки передаются нормально и при "OPT = s"

Большой проблемы нет, так как с самдельной задержкой вроде бы работает.
Но хотелось бы узнать причину, чтобы не получить проблем в дальнейшем.
_______
Как правильно использовать _delay_ms(), чтобы работало и при оптимизации?

Код
//код . . .

char *StringLCD;
char Hello_1[]= "11111111111111111111111111111111";
char Hello_2[]= "22222222222222222222222222222222";

//------------------------------------------------------
int main(void)
{
init();

UDR= Address_1;// пошлем адрес
StringLCD= Hello_1;
UCSRB|= (1<<UDRIE);//и отправим нужную строку
_delay_ms(2000);

UDR= Address_1;// пошлем адрес
StringLCD= Hello_2;
UCSRB|= (1<<UDRIE);//и отправим нужную строку
_delay_ms(2000);

for(;;);
return 0;
}
//------------------------------------------------------
ISR(USART_UDRE_vect)
{
    static uint8_t    j= 0;
    if(j< 32)
    {
        UDR= StringLCD[j++];
    }
    else
    {
        j=0;
        UCSRB&= ~(1<<UDRIE);
    }
}
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
Сергей Борщ
сообщение Nov 8 2010, 09:08
Сообщение #2


Гуру
******

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



Цитата(artymen @ Nov 6 2010, 12:32) *
Возможно, плагин кривой, что выбираемый мною девайс не передается линковщику для задания нужной конфигурации. Как бы то ни было, это не мои грабли, я всего лишь указал на баг.
О. уже плагин. А вовсе и не gcc и не avr-libc.
Цитата(MrYuran @ Nov 6 2010, 09:37) *
Речь-то про ms, а не mks
Смысла делать миллисекундные задержки "на NOP-ах" я тоже никакого не вижу.
Лично я при таких задержках отпускаю процессор заниматься другими делами.
Хоть это и несколько сложнее, чем просто тупождать.
Да какая разница. У меня есть инициализация LCD. Одного-единственного. Она выполняется один раз при включении. В конструкторе. ОС на этот момент не запущена, отпускать проц некуда. Так накой мне городить службу времени на таймерах, если тупой цикл занимает гораздо меньше места, а индикатору (не говоря уж о пользователе - он не заметит разницы) не критично затягивание задержек? Мне нужно при старте включить подтяжку, дать паузу ~1 мс на заряд паразитных емкостей и прочитать состояние ноги. Опять на таймерах городить? Но процессору все равно больше нечем заниматься пока не прочитает состояние той ноги, и точность (в плюс) задержки не критична нисколько.


Цитата(alexeyv @ Nov 8 2010, 07:07) *
При посылке ПЕРВОГО байта прерывание USART_UDRE_vect возникает СРАЗУ ЖЕ,
Отчего же? Флаг установится, (точнее он и перед этим стоял), а прерывание возникнет после его разрешения в строке UCSRB|= (1<<UDRIE);//и отправим нужную строку


--------------------
На любой вопрос даю любой ответ
"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
Laksus
сообщение Nov 8 2010, 22:16
Сообщение #3


Частый гость
**

Группа: Участник
Сообщений: 146
Регистрация: 16-05-05
Пользователь №: 5 069



Цитата(Сергей Борщ @ Nov 8 2010, 12:08) *
... Так накой мне городить службу времени на таймерах
...
процессору все равно больше нечем заниматься ...

Вы прямо-таки сформулировали мои мысли, прочитав я на какое-то мгновение засомневался, не цитата ли из моего сообщения, я хотел отправить очень похожее (по сути), уже набрал, но потом решил отложить. Абсолютно согласен, проц некуда отпускать, а кроме паразитных емкостей мне еще надо ждать установки RC-цепочек.
___
volatile не помогает, ничего не меняется.
___
Причина не в _delay_ms(2000), если по прерываниям таймера наращивать счетчик (Count++),
а паузу между выводимыми строчками сделать через ожидание пока счетчик натикает нужное число
while(Count < 20); , или if(Count==20)..., то все равно не работает так как казалось бы должно.

Просто оптимизатор считает, что нефиг присваивать одной и той же переменной несколько значений подряд.

Если присваивать в прерывании таймера, тогда все нормально.
Но так как мне очень не хочется путаться с пусковым приветом в прерывании, где будет вся работа программы, то
я лучше использую таки _delay_ms(2000), а для передачи текста использую не указатели, а функцию strcpy(). Ее оптимизатор не выкидывает. Все работает так как мне хотелось.

Насколько я понял для правильного выхода из возникшей ситуации мне надо бы глубоко изучить внутреннюю кухню gcc.
А через strcpy() может и неправильно (быстродействие, размер кода), но так как быстродействия мне не надо, и код (предположительно) влезет с запасом, то меня устраивает и такое половинчатое решение.
Код
char StringLCD[33];
. . .
int main(void)
{
init();

UDR= Address_LCD;// пошлем адрес
strcpy(StringLCD, Hello_1);
UCSRB|= (1<<UDRIE);//и отправим строку1
_delay_ms(2000);

UDR= Address_LCD;// пошлем адрес
strcpy(StringLCD, Hello_2);
UCSRB|= (1<<UDRIE);//и отправим строку2
. . .
for(;;);


Спасибо ответившим.

Сообщение отредактировал Laksus - Nov 8 2010, 22:23
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Nov 10 2010, 08:33
Сообщение #4


Гуру
******

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



Цитата(Laksus @ Nov 9 2010, 00:16) *
___
volatile не помогает, ничего не меняется.
___
Покажите, как вы его применили. Сдается, что вы вместо volatile-указателя на char объявили указатель на volatile char. Потому и не помогло.
alexeyv - насчет безликого init() согласен. Но раз дальше идет разрешение прерывания UDRIE, то логично предположить что оно было запрещено до этого. Иначе бы мы просто постоянно крутились в его обработчике.


--------------------
На любой вопрос даю любой ответ
"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
Laksus
сообщение Nov 10 2010, 11:15
Сообщение #5


Частый гость
**

Группа: Участник
Сообщений: 146
Регистрация: 16-05-05
Пользователь №: 5 069



Цитата(Сергей Борщ @ Nov 10 2010, 11:33) *
... Сдается, что вы вместо volatile-указателя на char объявили указатель на volatile char. Потому и не помогло. ...

Так точно! Я ж эту volatile пытался влепить в кучу мест (примерно как мартышка очки), и только после звездочки не догадался (она ж у меня вплотную к переменной пририсована, вот как-то в голову и не пришло, .что туды можно что-то добавить.)
Код
    char *volatile StringLCD;//  работает так как хотел


Большое спасибо за помощь.
Хоть в данном случае большой проблемы и не было, но в дальнейшем незнание разницы между volatile-указателем и укзателем на volatle еще не раз бы о себе напомнило. (Хотя я пока еще толком не понял этой разницы, но гугль говорит, что на эти грабли настапают многие. Есть много обсуждений этого вопроса, почитаю, надеюсь пойму.)

Go to the top of the page
 
+Quote Post

Сообщений в этой теме
- Laksus   WinAVR, _delay_ms(), строки и оптимизация.   Nov 5 2010, 19:17
- - artymen   Функции из util/delay.h имеют одну пакость, из док...   Nov 5 2010, 19:46
|- - Laksus   Цитата(artymen @ Nov 5 2010, 22:46) ... п...   Nov 5 2010, 22:52
|- - ASZ   Может, это снобизм, но принципиально не использую ...   Nov 5 2010, 23:09
- - Genadi Zawidowski   У функции _delay_ms() есть ограничение на максимал...   Nov 5 2010, 19:48
- - artymen   Посмотрите, укладывается ли полученный бинарник во...   Nov 6 2010, 05:12
|- - Сергей Борщ   Цитата(artymen @ Nov 6 2010, 08:12) GCC (...   Nov 6 2010, 06:44
|- - MrYuran   Цитата(Сергей Борщ @ Nov 6 2010, 09:44) К...   Nov 6 2010, 07:37
- - artymen   ЦитатаФигня полная. Прекрасно следит. А если у вас...   Nov 6 2010, 10:32
- - alexeyv   Маленькое замечание по поводу кода: КодUDR= Addre...   Nov 8 2010, 05:07
||- - Qwertty   Цитата(Laksus @ Nov 9 2010, 02:16) Просто...   Nov 8 2010, 23:06
||- - Сергей Борщ   Цитата(Laksus @ Nov 10 2010, 13:15) но в ...   Nov 10 2010, 11:55
|- - alexeyv   Цитата(Сергей Борщ @ Nov 8 2010, 14:08) О...   Nov 9 2010, 04:23
- - Marian   При уровне оптимизации -Os, компилятор выкидывает ...   Nov 8 2010, 14:56


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

 


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


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