|
|
  |
WinAVR-20100110, Пишем отзывы сюда |
|
|
|
Jan 21 2010, 14:34
|

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

|
Цитата(Сергей Борщ @ Jan 17 2010, 00:36)  Размеры проектов - 1836->1854 (загрузчик) и 6042->5816 (приложение, мега8, С++, виртуальные функции). Работоспособность не проверял. Проверил. Код работает. Сравнил листинги (правда для другого проекта). Основное отличие - обращение к eeprom. В 20090313 процедура чтения|записи блока принимала в качестве параметра указатель на функцию чтения|записи байта и косвенно вызывала эту функцию. Теперь функция чтения/записи байта встроена в чтение/запись блока, благодаря чему экономится место как на загрузке указателя так и на перетасовке регистров при косвенном вызове. В 20100110 вся процедура чтения/записи блока (со встроенным обращением) меньше, чем обертка вызова функции чтения/записи байта в 20090313. Кроме этого в 20090313 независимо от -msave-prologue запись/чтение блока вызывала процедуры сохранения/восстановления регистров, которые в 20100110 не понадобились. Результат - уменьшение кода на 148 байт. В остальном код на этом конкретном проекте идентичный до байта. Вывод - теперь можно смело использовать eeprom_read_block(). В 20090313 эффективнее получалось вручную читать побайтно в цикле. Остался недостаток оптимизации при работе с байтовыми аргументами функций: При вызове функции, объявленной с аргументом типа "байт" в регистры заносится 2 байта (старший = 0), внутри функции копия аргумента тоже хранится как двухбайтовая переменная, хотя используется только младший байт: Код void hd44780::write_data(uint8_t byte) 162: ff 92 push r15 164: 0f 93 push r16 166: 1f 93 push r17 <----------------------------------- 168: 8c 01 movw r16, r24 <----------------------------------- 16a: f6 2e mov r15, r22 { write_tetrade(byte & 0xF0); 16c: 60 7f andi r22, 0xF0; 240 16e: ec df rcall .-40 ; 0x148 <_ZN7hd4478013write_tetradeEh> write_tetrade(byte << 4); 170: f2 94 swap r15 172: 80 ef ldi r24, 0xF0; 240 174: f8 22 and r15, r24 176: c8 01 movw r24, r16 <----------------------------------- 178: 6f 2d mov r22, r15 17a: e6 df rcall .-52 ; 0x148 <_ZN7hd4478013write_tetradeEh> 17c: 8d e3 ldi r24, 0x3D; 61 17e: 8a 95 dec r24 180: f1 f7 brne .-4 ; 0x17e <_ZN7hd4478010write_dataEh+0x1c> _delay_us(50); ON(LCD_RS); 182: c1 9a sbi 0x18, 1; 24 } 184: 1f 91 pop r17 <----------------------------------- 186: 0f 91 pop r16 188: ff 90 pop r15 18a: 08 95 ret
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Jan 27 2010, 12:16
|
Группа: Участник
Сообщений: 10
Регистрация: 11-08-08
Из: г. Тверь
Пользователь №: 39 554

|
Ошибку в прологе/эпилоге при использовании ISR(xxx_vect, ISR_NOBLOCK) так и не исправили  Проект для меги1280 на С++ в 14КБ собрался на 150 байт меньше, это хорошо.
|
|
|
|
|
Feb 8 2010, 06:04
|

Профессионал
    
Группа: Участник
Сообщений: 1 620
Регистрация: 22-06-07
Из: Санкт-Петербург, Россия
Пользователь №: 28 634

|
Цитата Code: #include <avr/io.h> volatile uint8_t v;
int main(void) { while (1) { v; v; v; #if BUG uint8_t* p = (uint8_t*) &v; PORTC = *p; #endif } }
avr-gcc 3.4.6 (WinAVR-20060421): Code:
.text .global main .type main, @function main:
ldi r28,lo8(__stack - 0) ldi r29,hi8(__stack - 0) out __SP_H__,r29 out __SP_L__,r28
lds r25,v .L2: lds r24,v lds r24,v lds r24,v out 40-0x20,r25 rjmp .L2 (yes, first lds is placed out of loop)
avr-gcc 4.1.2 (WinAVR-20070525) - the same except no stack pointer initialisation avr-gcc 4.2.2 (WinAVR=20071221) - the same except no stack pointer initialisation avr-gcc 4.3.2 (WinAVR-20081205) and later - as WinAVR-20100110 А чего тут криминального? Чтений из volatile ровно столько, сколько надо. А от чтения по указателю на простой (не volatile) тип - ничего, кроме знаачения не гарантируется. А откуда оно его взяло - целиком на усмотрение оптимизатора. Вообще, всё что не volatile, может быть "закешированно" при входе в функцию и записано перед выходом из неё или вызовом чего-либо.
|
|
|
|
|
Feb 8 2010, 10:48
|

Нечётный пользователь.
     
Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417

|
Цитата(Genadi Zawidowski @ Feb 8 2010, 08:04)  А чего тут криминального? Тут всё нормально. Вы посмотрите что из этого делают версии WinAVR-2008, 2009 и та 2010, которая в теме и обсуждается. Там из v при -DBUG=1 делется одно чтение. Вот это "as WinAVR-20100110" Код .global main .type main, @function main: .L2: lds r24,v out 53-32,r24 rjmp .L2 У Klen-сборок 4.4.0 и 4.5.0 и у WinAVR по 20071221 включительно (т.е. по 4.2.x включительно) всё нормально. Т.е. - похоже, что ошибка в 4.3.x Цитата(Genadi Zawidowski @ Feb 8 2010, 08:04)  Вообще, всё что не volatile, может быть "закешированно" при входе в функцию и записано перед выходом из неё или вызовом чего-либо. И, если не зависит друг от друга, то переставлено местами (в том числе и с обращениями к volatile), и вообще выброшено. А то я этого не знаю :-)
--------------------
Ну, я пошёл… Если что – звоните…
|
|
|
|
|
Feb 8 2010, 12:59
|
;
     
Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509

|
Цитата(ReAl @ Feb 5 2010, 01:24)  Однако... Однако, дубль два. Имеем: Код double res; //.............. return (int16_t) (lround(res) - 273); Скомпилировано с опцией -mint8Получаем: Код +000007BC: 01C8 MOVW R24,R16 +000007BD: 01B7 MOVW R22,R14 +000007BE: D12D RCALL PC+0x012E // lround(res) R23:R22:r25:r24 = 0x01870000 +000007BF: 019C MOVW R18,R24 // осторожно, грабли! +000007C0: 5121 SUBI R18,0x11 // - 273 +000007C1: 4031 SBCI R19,0x01 +000007C2: 01C9 MOVW R24,R18 Вместо того чтобы правильный результат в старшей половине, отдает ноль. Без опции -mint8 - все нормально. Просьба советы никогда не применять указанную опцию не давать!  А вначале был оч.рад, когда используя stdint.h получал утоптанные выражения целого типа. Недолго музыка играла.
|
|
|
|
|
Feb 12 2010, 17:49
|
;
     
Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509

|
Цитата(_Pasha @ Feb 8 2010, 16:59)  Однако, дубль два.  Боян оказываеццо, с 2004 года так и не удосужились подрихтовать. Еще прикол. Кто нибудь знает, как избавиться от неправильного назначения регистровых пар? Например, имеем указатель на структуру, и поля в ней интенсивно используются. Сабж так любит регистры XH:XL, что поручает именно Х эту непосильную работу. В итоге, послав все к чертям, я прибил эти регистры Код register volatile uint8_t xL asm("r26"); register volatile uint8_t xH asm("r27"); Компилер немедленно взялся за ум и функция изрядно похудела, т.к. пошли в ход инструкции LDD/STD  Неужели эту фигню никогда не причешут? А у KGP как с этим дела? (Нету времени попробовать...)
|
|
|
|
|
Feb 17 2010, 06:59
|
;
     
Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509

|
 Ау, я что, в палате №6? Не спим! Нашел серьезную багу. Предположим, имеется глобальная переменная или extern Код uint8_t period; Попытка сделать задаром арифметическую операцию по модулю 100, например так Код period += 33; if(period > 100) period -= 100; Приводит к созданию неожиданного кода, наподобие Код lds r24,period subi r24,0xdf // period += 33 cpi r24,0x64 brlo label subi r24,0x43 // !!! а должно быть 0x64 label: Оптимизация -Os Это катастрофа. У оптимизатора появилась ложная зависимость, и он посчитал что надо вычесть не 100, а 100-33 = 67 Сколько таких случаев надо отсматривать в листинге - ХЗ Мне повезло, что вносилась доработка в уже готовое софто. Проблема имеет workaround, як кажуть кляті англійці Для того, чтобы код выполнялся правильно, надо period объявить volatile Такие дела. Видимо, придется возвращаться в WinAVR-20071221
|
|
|
|
|
Feb 17 2010, 15:39
|
Знающий
   
Группа: Свой
Сообщений: 716
Регистрация: 27-05-05
Из: Kyiv
Пользователь №: 5 454

|
Друг спросил как разместить данные во флеш поопределенному адресу. Сделал как по ссылке. http://8515.avrfreaks.net/index.php?name=P...ic&p=589365WinAVR-20100110. Судя по листингу программа обращается к данным как задано Код const uint8_t part_number __attribute__ ((section (".part_number")))='A';
i = pgm_read_byte(&part_number); 2ee: e0 ef ldi r30, 0xF0; 240 2f0: ff e3 ldi r31, 0x3F; 63 2f2: e4 91 lpm r30, Z+ Но ни в HEX ни в bin файле нету данных. Обычное объявление переменных в памяти программ работает. Совместить два аттрибута у меня не получилось.
|
|
|
|
|
Feb 17 2010, 17:50
|

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

|
Цитата(misyachniy @ Feb 17 2010, 17:39)  Но ни в HEX ни в bin файле нету данных. попробйте обозвать секцию .text.partnumber или .progmem.partnumber Я указываю секцию в скрипте линкера, --section-start не пользовался.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Feb 17 2010, 19:45
|

Чайник, 1 литр
   
Группа: Свой
Сообщений: 655
Регистрация: 17-05-06
Из: Moscow
Пользователь №: 17 168

|
Цитата(_Pasha @ Feb 17 2010, 09:59)  Нашел серьезную багу. Воссоздать не получается. Используется два регистра, оттуда и такой подход с константами: Код lds r25,period mov r24,r25 subi r24,lo8(-(33)) sts period,r24 cpi r24,lo8(101) brlo .L3 subi r25,lo8(-(-67)) sts period,r25 .L3 Дайте проект, в котором у вас такая ошибка возникает, ибо пока не понятно (доприбивались вы регистры, хехе  ). -- Цитата(misyachniy @ Feb 17 2010, 18:39)  Сделал как по ссылке. Тоже сделал. Данные все на месте. Разница в оптимизации? Показывайте Makefile.
|
|
|
|
|
Feb 17 2010, 19:53
|

Нечётный пользователь.
     
Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417

|
Цитата(_Pasha @ Feb 17 2010, 08:59)  Попытка сделать задаром арифметическую операцию по модулю 100, например так ... Оптимизация -Os Это катастрофа. У оптимизатора появилась ложная зависимость, и он посчитал что надо вычесть не 100, а 100-33 = 67 Мне не удалось полeчить такую бяку. Код странноватый (оптимизатор явно перемудрил) но корректный. Более того - он не отличается от кода 20071221 Код #include <avr/io.h> extern uint8_t period;
void foo() { period += 33; if(period > 100) period -= 100; }
uint8_t moo(uint8_t i) { i += 33; if(i > 100) i -= 100; return i; } -Os Код .text .global foo .type foo, @function foo: lds r25,period mov r24,r25 subi r24,lo8(-(33)) sts period,r24 cpi r24,lo8(101) brlo .L3 subi r25,lo8(-(-67)) ; 67 вычитается из _исходного_ значения (+33-100) <=> (-67) sts period,r25 .L3: ret
.global moo .type moo, @function moo: subi r24,lo8(-(33)) cpi r24,lo8(101) brlo .L5 subi r24,lo8(-(-100)) .L5: ret
--------------------
Ну, я пошёл… Если что – звоните…
|
|
|
|
|
Feb 18 2010, 09:49
|
Знающий
   
Группа: Свой
Сообщений: 716
Регистрация: 27-05-05
Из: Kyiv
Пользователь №: 5 454

|
Цитата(Сергей Борщ @ Feb 17 2010, 19:50)  попробйте обозвать секцию .text.partnumber или .progmem.partnumber Я указываю секцию в скрипте линкера, --section-start не пользовался. Переобъявил, секция попала сразу за таблицей векторов. Как в скрипте линкера без --section-start настраивать я не умею. Код код const uint8_t part_number __attribute__ ((section (".progmem.part_number")))='A'; const unsigned long serial_number __attribute__ ((section (".progmem.serial_number"))) = 0x12345678;
маке LDFLAGS += -Wl,--section-start=.progmem.part_number=$(PART_NUMBER_ADDRESS) LDFLAGS += -Wl,--section-start=.progmem.serial_number=$(SERIAL_NUMBER_ADDRESS)
HEX :100050000C9458 0041 78563412 456E7465722063D2
LST 00000054 <part_number>: 54: 41 A
i = pgm_read_byte(&part_number); 2f4: e4 e5 ldi r30, 0x54; 84 2f6: f0 e0 ldi r31, 0x00; 0 2f8: e4 91 lpm r30, Z+
|
|
|
|
|
  |
4 чел. читают эту тему (гостей: 4, скрытых пользователей: 0)
Пользователей: 0
|
|
|