Перейти к содержанию
    

Переобъявил, секция попала сразу за таблицей векторов.
"Ну тогда не знаю :laughing: "

Как в скрипте линкера без --section-start настраивать я не умею.
Идете в WinAVR/avr/lib/ldscripts, берете там скрипт для своего семейства, копируете в проект, правите, добавляете к ключам линкера LDFLAGS += -Wl,-T,<имя скрипта> и получаете полный контроль над адресным пространством. Вот пример для загрузчика m88 (регион и секция serial_no):
/* 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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Забавный прикол:

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>

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Мне не удалось полeчить такую бяку. Код странноватый (оптимизатор явно перемудрил) но корректный.

Так. Вернувшись к вопросу, вынужден признать, что воссоздать ошибку снова мне не удалось. Это означает, что я поспешил с выводами. Приношу свои искренние извинения. Теперь осталось найти истинную причину, почему для получения рабочей программы требовалось volatile... :07:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вот пример для загрузчика m88

Кстати - столкнулся с проблемой написания загрузчика на мегу48. Условия уродливые - надо расшаривать протокол связи. В связи с этим разбил программу на две части :

vectors
fixed_boot
progmem
init0
итд итп

В секцию fixed_boot помещаю весь протокол, контр.сумму и стартап.

После этого остутствует необходимость в таблице системных вызовов, обращаться в мини-биосу можно обычными вызовами функций, т.к. эта часть намертво пришпилена после таблицы векторов

Кто что думает о таком варианте?

UPD: makefile был с ошибкой. Исправлено

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

т.к. эта часть намертво пришпилена после таблицы векторов
До первой найденой ошибки или добавления еще одной функции в протокол.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

До первой найденой ошибки или добавления еще одной функции в протокол.

Обойти можно - в #ifdef-ах исходника предусмотреть часть, которая просто копирует страницы флеша из одного места в другое, обновляя только биос.

А прямее путь кто-нить знает?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Еще прикол. Кто нибудь знает, как избавиться от неправильного назначения регистровых пар?

...

Компилер немедленно взялся за ум и функция изрядно похудела, т.к. пошли в ход инструкции LDD/STD

:cranky: Неужели эту фигню никогда не причешут?

А у KGP как с этим дела? (Нету времени попробовать...)

Тоже так и не попробовал, но наткнулся недавно на avrfreaks на линк сюда

https://www.mikrocontroller.net/topic/65923#530326

Костыль, конечно, но на всякий случай запасся.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

а я вот не увидел в этой версии компилятора опции -relax... или я куда-то не туда смотрю?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

или я куда-то не туда смотрю?
Это опция линкера.

LDFLAGS += -Wl,-relax

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

во блин... странно... вчера вроде не получалось обнаружить эффект, а сегодня получилось... извините за беспокойство - я прошляпил...

 

P.S. что это опция линкера - я и был в курсе...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Возможно уже такой вопрос был, сходу не нашел.

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.

Каким образом можно это победить ?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Каким образом можно это победить ?
Использовать атрибуты OS_main, OS_task? http://electronix.ru/forum/index.php?s=&am...st&p=441344

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Использовать атрибуты OS_main, OS_task? http://electronix.ru/forum/index.php?s=&am...st&p=441344

Спасибо, помогло. OS_main убирает ненужные заталкивания в стек, но call main все равно остается )

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

call main все равно остается )

Это уже из области стартапа. Поменяйте в стартапе rcall на rjmp

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Кто-нибудь может объяснить феномен. -Os

#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;
}

Листинг правильный - его не привожу, т.к. все тривиально

Дальше, если это сделать в таком виде

#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;
}

Листинг - конец света. Выкинул, родимый, все на корню.

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++) ? :cranky:

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...