|
|
  |
WinAVR-20100110, Пишем отзывы сюда |
|
|
|
Feb 18 2010, 11:32
|

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

|
Цитата(misyachniy @ Feb 18 2010, 11:49)  Переобъявил, секция попала сразу за таблицей векторов. "Ну тогда не знаю  " Цитата(misyachniy @ Feb 18 2010, 11:49)  Как в скрипте линкера без --section-start настраивать я не умею. Идете в WinAVR/avr/lib/ldscripts, берете там скрипт для своего семейства, копируете в проект, правите, добавляете к ключам линкера LDFLAGS += -Wl,-T,<имя скрипта> и получаете полный контроль над адресным пространством. Вот пример для загрузчика m88 (регион и секция serial_no): CODE /* ATmega88 bootloader linker script */ OUTPUT_FORMAT("elf32-avr","elf32-avr","elf32-avr") OUTPUT_ARCH(avr:4) MEMORY { application (rx) : ORIGIN = 0, LENGTH = 7K bootloader (rx) : ORIGIN = 7K, LENGTH = 1K - 4 serial_no (rx) : ORIGIN = 8K-4, LENGTH = 4 ram (rw!x) : ORIGIN = 0x800100, LENGTH = 1K eeprom (rw!x) : ORIGIN = 0x810000, LENGTH = 512 } SECTIONS { /* Internal text space or external memory. */ .app : { __app_start = . ; /* reserve space */ . = 7K; __app_end = . ; } > application __app_len = . - __app_start; .text : { KEEP(*(.vectors)) /* For data that needs to reside in the lower 64k of progmem. */ *(.progmem.gcc*) *(.progmem*) . = ALIGN(2); __trampolines_start = . ; /* The jump trampolines for the 16-bit limited relocs will reside here. */ *(.trampolines) *(.trampolines*) __trampolines_end = . ; /* For future tablejump instruction arrays for 3 byte pc devices. We don't relax jump/call instructions within these sections. */ *(.jumptables) *(.jumptables*) /* For code that needs to reside in the lower 128k progmem. */ *(.lowtext) *(.lowtext*) __ctors_start = . ; KEEP(SORT(*)(.ctors)) __ctors_end = . ; __dtors_start = . ; KEEP(SORT(*)(.dtors)) __dtors_end = . ; /* From this point on, we don't bother about wether the insns are below or above the 16 bits boundary. */ KEEP (*(.init0)) /* Start here after reset. */ KEEP (*(.init1)) KEEP (*(.init2)) /* Clear __zero_reg__, set up stack pointer. */ KEEP (*(.init3)) KEEP (*(.init4)) /* Initialize data and BSS. */ KEEP (*(.init5)) KEEP (*(.init6)) /* C++ constructors. */ KEEP (*(.init7)) KEEP (*(.init8)) KEEP (*(.init9)) /* Call main(). */ *(.text) . = ALIGN(2); *(.text.*) . = ALIGN(2); KEEP (*(.fini9)) /* _exit() starts here. */ KEEP (*(.fini8)) KEEP (*(.fini7)) KEEP (*(.fini6)) /* C++ destructors. */ KEEP (*(.fini5)) KEEP (*(.fini4)) KEEP (*(.fini3)) KEEP (*(.fini2)) KEEP (*(.fini1)) KEEP (*(.fini0)) /* Infinite loop after program termination. */ _etext = . ; } > bootloader
.data : { PROVIDE (__data_start = .) ; *(.gnu.linkonce.d*) *(.rodata) *(.rodata*) *(.data) *(.data*) . = ALIGN(2); _edata = . ; PROVIDE (__data_end = .) ; } > ram AT > bootloader
.bss : { PROVIDE (__bss_start = .) ; *(.bss) *(.bss*) *(COMMON) PROVIDE (__bss_end = .) ; } > ram __data_load_start = LOADADDR(.data); __data_load_end = __data_load_start + SIZEOF(.data); .serial_no : { KEEP(*(.serial_no)) } > serial_no
/* Global data not cleared after reset. */ .noinit : { PROVIDE (__noinit_start = .) ; *(.noinit*) PROVIDE (__noinit_end = .) ; _end = . ; PROVIDE (__heap_start = .) ; } > ram
.eeprom : { *(.eeprom*) __eeprom_end = . ; } > eeprom
/* Stabs debugging sections. */ .stab 0 : { *(.stab) } .stabstr 0 : { *(.stabstr) } .stab.excl 0 : { *(.stab.excl) } .stab.exclstr 0 : { *(.stab.exclstr) } .stab.index 0 : { *(.stab.index) } .stab.indexstr 0 : { *(.stab.indexstr) } .comment 0 : { *(.comment) }
/* DWARF debug sections. Symbols in the DWARF debugging sections are relative to the beginning of the section so we begin them at 0. */ /* DWARF 1 */ .debug 0 : { *(.debug) } .line 0 : { *(.line) } /* GNU DWARF 1 extensions */ .debug_srcinfo 0 : { *(.debug_srcinfo) } .debug_sfnames 0 : { *(.debug_sfnames) } /* DWARF 1.1 and DWARF 2 */ .debug_aranges 0 : { *(.debug_aranges) } .debug_pubnames 0 : { *(.debug_pubnames) } /* DWARF 2 */ .debug_info 0 : { *(.debug_info) *(.gnu.linkonce.wi.*) } .debug_abbrev 0 : { *(.debug_abbrev) } .debug_line 0 : { *(.debug_line) } .debug_frame 0 : { *(.debug_frame) } .debug_str 0 : { *(.debug_str) } .debug_loc 0 : { *(.debug_loc) } .debug_macinfo 0 : { *(.debug_macinfo) } } И еще - мне показалось удобнее хранить не константу серийного номера, а функцию, возвращающую серийный номер. А уже в код самой функции на этапе программирования подставлять коды LDI с серийным номером (avreal умеет). Это позволяет разместить такой серийник в защищенном от чтения по LPM загрузчике и тратить на чтение один ( R )CALL вместо сохранения Z, его загрузки, LPM, восстановления Z: Код __attribute__((section(".serial_no"), noinline)) uint8_t serial_no() { return 0; }
177 .section .serial_no,"ax",@progbits 178 .global serial_no 180 serial_no: 181 .LFB15: 182 .LSM26: 183 /* prologue: function */ 184 /* frame size = 0 */ 185 .LSM27: 186 0000 80E0 ldi r24,lo8(0) 187 /* epilogue start */ 188 0002 0895 ret
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Feb 19 2010, 14:25
|

неотягощённый злом
     
Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643

|
Забавный прикол: Код uint16_t x; .... if ((x&1)==0) {...} // случай 1 if (!(x&1)) {...} // случай 2 Получаем листинг: Код // случай 1: 1fd3c: 20 fd sbrc r18, 0 1fd3e: 03 c0 rjmp .+6 ; 0x1fd46 <main+0x4e4>
// случай 2 1fd40: c9 01 movw r24, r18 1fd42: 81 70 andi r24, 0x01; 1 1fd44: 90 70 andi r25, 0x00; 0 1fd46: 89 2b or r24, r25 1fd48: 19 f4 brne .+6 ; 0x1fd50 <main+0x4ee>
--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
|
|
|
|
|
Mar 16 2010, 18:05
|
;
     
Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509

|
Цитата(Сергей Борщ @ Feb 18 2010, 15:32)  Вот пример для загрузчика m88 Кстати - столкнулся с проблемой написания загрузчика на мегу48. Условия уродливые - надо расшаривать протокол связи. В связи с этим разбил программу на две части : Код vectors fixed_boot progmem init0 итд итп В секцию fixed_boot помещаю весь протокол, контр.сумму и стартап. После этого остутствует необходимость в таблице системных вызовов, обращаться в мини-биосу можно обычными вызовами функций, т.к. эта часть намертво пришпилена после таблицы векторов[attachment=41881:qstart.zip] Кто что думает о таком варианте? UPD: makefile был с ошибкой. Исправлено
|
|
|
|
|
Mar 20 2010, 13:24
|

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

|
Цитата(_Pasha @ Feb 12 2010, 19:49)  Еще прикол. Кто нибудь знает, как избавиться от неправильного назначения регистровых пар? ... Компилер немедленно взялся за ум и функция изрядно похудела, т.к. пошли в ход инструкции LDD/STD  Неужели эту фигню никогда не причешут? А у KGP как с этим дела? (Нету времени попробовать...) Тоже так и не попробовал, но наткнулся недавно на avrfreaks на линк сюда https://www.mikrocontroller.net/topic/65923#530326Костыль, конечно, но на всякий случай запасся.
--------------------
Ну, я пошёл… Если что – звоните…
|
|
|
|
|
Mar 25 2010, 08:56
|

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

|
Цитата(ARV @ Mar 25 2010, 10:45)  или я куда-то не туда смотрю? Это опция линкера. LDFLAGS += -Wl,-relax
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Aug 19 2010, 13:22
|
Местный
  
Группа: Свой
Сообщений: 230
Регистрация: 7-04-08
Из: Украина, Запорожье
Пользователь №: 36 541

|
Возможно уже такой вопрос был, сходу не нашел. WINAVR 20100110: Код 000006a0 <.do_clear_bss_start>: 6a0: a2 3f cpi r26, 0xF2; 242 6a2: b1 07 cpc r27, r17 6a4: e1 f7 brne .-8 ; 0x69e <.do_clear_bss_loop> 6a6: 0e 94 b3 03 call 0x766; 0x766 <main> 6aa: 0c 94 0c 3d jmp 0x7a18; 0x7a18 <_exit> Ну и собственно: Код int main (void) { 766: 2f 92 push r2 768: 3f 92 push r3 76a: 4f 92 push r4 76c: 5f 92 push r5 76e: 6f 92 push r6 770: 7f 92 push r7 772: 8f 92 push r8 774: 9f 92 push r9 776: af 92 push r10 778: bf 92 push r11 77a: cf 92 push r12 77c: df 92 push r13 77e: ef 92 push r14 780: ff 92 push r15 782: 0f 93 push r16 784: 1f 93 push r17 786: cf 93 push r28 788: df 93 push r29 Зачем call main и зачем так загаживать стек ? В старых версиях, если не ошибаюсь, был rjmp main. Каким образом можно это победить ?
|
|
|
|
|
Feb 8 2011, 07:48
|
;
     
Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509

|
Кто-нибудь может объяснить феномен. -Os CODE #include <avr/io.h> int main(void); volatile uint32_t interf; int main(void) { while(PINB & 4) { uint32_t data=0; for(uint8_t msk=0;msk < 24; msk++) { PORTB |= 0x80; if(PINB & 0x40) data |= 1; data <<= 1; PORTB &= 0x7F; } interf = data; } return 0; }
Листинг правильный - его не привожу, т.к. все тривиально Дальше, если это сделать в таком виде CODE #include <avr/io.h> int main(void); volatile uint32_t interf; int main(void) { while(PINB & 4) { uint32_t data; for(uint8_t msk=0,data=0;msk < 24; msk++) { PORTB |= 0x80; if(PINB & 0x40) data |= 1; data <<= 1; PORTB &= 0x7F; } interf = data; } return 0; }
Листинг - конец света. Выкинул, родимый, все на корню. CODE int main(void) { 44: 0f c0 rjmp .+30 ; 0x64 <main+0x20> while(PINB & 4) 46: 80 e0 ldi r24, 0x00 ; 0 { uint32_t data; for(uint8_t msk=0,data=0;msk < 24; msk++) { PORTB |= 0x80; 48: c7 9a sbi 0x18, 7 ; 24 if(PINB & 0x40) data |= 1; 4a: 96 b3 in r25, 0x16 ; 22 data <<= 1; PORTB &= 0x7F; 4c: c7 98 cbi 0x18, 7 ; 24 int main(void) { while(PINB & 4) { uint32_t data; for(uint8_t msk=0,data=0;msk < 24; msk++) 4e: 8f 5f subi r24, 0xFF ; 255 50: 88 31 cpi r24, 0x18 ; 24 52: d1 f7 brne .-12 ; 0x48 <main+0x4> PORTB |= 0x80; if(PINB & 0x40) data |= 1; data <<= 1; PORTB &= 0x7F; } interf = data; 54: 10 92 60 00 sts 0x0060, r1 58: 10 92 61 00 sts 0x0061, r1 5c: 10 92 62 00 sts 0x0062, r1 60: 10 92 63 00 sts 0x0063, r1 #include <avr/io.h> int main(void); volatile uint32_t interf; int main(void) { while(PINB & 4) 64: b2 99 sbic 0x16, 2 ; 22 66: ef cf rjmp .-34 ; 0x46 <main+0x2> PORTB &= 0x7F; } interf = data; } return 0; } 68: 80 e0 ldi r24, 0x00 ; 0 6a: 90 e0 ldi r25, 0x00 ; 0 6c: 08 95 ret
Что же такого крамольного в for(uint8_t msk=0,data=0;msk < 24; msk++) ?
|
|
|
|
|
  |
2 чел. читают эту тему (гостей: 2, скрытых пользователей: 0)
Пользователей: 0
|
|
|