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

bss и avr-gcc

После написания программ на arm с помощью gcc, было очень необычно для avr-gcc отсутствие явного загрузочного кода и явного lowlevelinit. Я так понимаю когда указываешь таргет mmcu, линкер сам знает какой прикомпилированный код прилинковать.

А реализованно ли в этом коде забивание нулями bss секции. И где эти исходники посмотреть можно?

 

И всегда ли при объявлении глобального массива элементов любого типа например он будет заполнен нулями?

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


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

После написания программ на arm с помощью gcc, было очень необычно для avr-gcc отсутствие явного загрузочного кода и явного lowlevelinit. Я так понимаю когда указываешь таргет mmcu, линкер сам знает какой прикомпилированный код прилинковать.

А реализованно ли в этом коде забивание нулями bss секции. И где эти исходники посмотреть можно?

 

И всегда ли при объявлении глобального массива элементов любого типа например он будет заполнен нулями?

Собственно lowlevelinit для меня до сих пор необычно.

В GNU toolchain загрузочный код находится в файлах crt0.S, crt1.S и прочих crt*.S.

Входят они в состав libc.

Исходники соответственно находятся в исходниках avr-libc.

Только что проинсталлировал себе ради интереса (я AVR не работаю).

 

main.c

char x[32];
int main(void)
{
    return 0;
}

 

Компилируем

avr-gcc -g3 -v -o tst main.c
Using built-in specs.
Target: avr
Configured with: ../build-tree/gcc-4.1.0/configure -v --enable-languages=c,c++ --prefix=/usr --infodir=/usr/share/info --mandir=/usr/share/man --enable-shared --with-system-zlib --enable-long-long --enable-nls --without-included-gettext --disable-checking --disable-libssp --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=avr
Thread model: single
gcc version 4.1.0
/usr/libexec/gcc/avr/4.1.0/cc1 -quiet -v -dD main.c -quiet -dumpbase main.c -auxbase main -g3 -version -o /tmp/ccBz19xB.s
ignoring nonexistent directory "/usr/lib/gcc/avr/4.1.0/../../../../avr/sys-include"
#include "..." search starts here:
#include <...> search starts here:
/usr/lib/gcc/avr/4.1.0/include
/usr/lib/gcc/avr/4.1.0/../../../../avr/include
End of search list.
GNU C version 4.1.0 (avr)
        compiled by GNU C version 4.1.2 20061115 (prerelease) (Debian 4.1.1-21).
GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
Compiler executable checksum: bac81a89e3092f468be596fb2b77fc06
/usr/lib/gcc/avr/4.1.0/../../../../avr/bin/as -o /tmp/ccKrQMt1.o /tmp/ccBz19xB.s
/usr/lib/gcc/avr/4.1.0/../../../../avr/bin/ld -m avr2 -o tst /usr/lib/gcc/avr/4.1.0/../../../../avr/lib/crts8515.o -L/usr/lib/gcc/avr/4.1.0 -L/usr/lib/gcc/avr/4.1.0 -L/usr/lib/gcc/avr/4.1.0/../../../../avr/lib /tmp/ccKrQMt1.o -lgcc -lc -lgcc

Смотрим перечень файлов при линковке (последняя команда). Используется файл crts8515.o значит исходник будет crts8515.S (не знаю, может для AVR это crts8515.asm)

Смотрим что получилось

amw@fox:~/tmp$ avr-objdump -S tst > tst.dump

 

Дамп дизассемблера.


tst:     file format elf32-avr

Disassembly of section .text:

00000000 <__vectors>:
  0:	0c c0       	rjmp	.+24     	; 0x1a <__ctors_end>
  2:	27 c0       	rjmp	.+78     	; 0x52 <__bad_interrupt>
  4:	26 c0       	rjmp	.+76     	; 0x52 <__bad_interrupt>
  6:	25 c0       	rjmp	.+74     	; 0x52 <__bad_interrupt>
  8:	24 c0       	rjmp	.+72     	; 0x52 <__bad_interrupt>
  a:	23 c0       	rjmp	.+70     	; 0x52 <__bad_interrupt>
  c:	22 c0       	rjmp	.+68     	; 0x52 <__bad_interrupt>
  e:	21 c0       	rjmp	.+66     	; 0x52 <__bad_interrupt>
 10:	20 c0       	rjmp	.+64     	; 0x52 <__bad_interrupt>
 12:	1f c0       	rjmp	.+62     	; 0x52 <__bad_interrupt>
 14:	1e c0       	rjmp	.+60     	; 0x52 <__bad_interrupt>
 16:	1d c0       	rjmp	.+58     	; 0x52 <__bad_interrupt>
 18:	1c c0       	rjmp	.+56     	; 0x52 <__bad_interrupt>

0000001a <__ctors_end>:
 1a:	11 24       	eor	r1, r1
 1c:	1f be       	out	0x3f, r1	; 63
 1e:	cf e5       	ldi	r28, 0x5F	; 95
 20:	d2 e0       	ldi	r29, 0x02	; 2
 22:	de bf       	out	0x3e, r29	; 62
 24:	cd bf       	out	0x3d, r28	; 61

00000026 <__do_copy_data>:
 26:	10 e0       	ldi	r17, 0x00	; 0
 28:	a0 e6       	ldi	r26, 0x60	; 96
 2a:	b0 e0       	ldi	r27, 0x00	; 0
 2c:	e4 e6       	ldi	r30, 0x64	; 100
 2e:	f0 e0       	ldi	r31, 0x00	; 0
 30:	03 c0       	rjmp	.+6      	; 0x38 <.do_copy_data_start>

00000032 <.do_copy_data_loop>:
 32:	c8 95       	lpm
 34:	31 96       	adiw	r30, 0x01	; 1
 36:	0d 92       	st	X+, r0

00000038 <.do_copy_data_start>:
 38:	a0 36       	cpi	r26, 0x60	; 96
 3a:	b1 07       	cpc	r27, r17
 3c:	d1 f7       	brne	.-12     	; 0x32 <.do_copy_data_loop>

0000003e <__do_clear_bss>:
 3e:	10 e0       	ldi	r17, 0x00	; 0
 40:	a0 e6       	ldi	r26, 0x60	; 96
 42:	b0 e0       	ldi	r27, 0x00	; 0
 44:	01 c0       	rjmp	.+2      	; 0x48 <.do_clear_bss_start>

00000046 <.do_clear_bss_loop>:
 46:	1d 92       	st	X+, r1

00000048 <.do_clear_bss_start>:
 48:	a0 38       	cpi	r26, 0x80	; 128
 4a:	b1 07       	cpc	r27, r17
 4c:	e1 f7       	brne	.-8      	; 0x46 <.do_clear_bss_loop>
 4e:	02 d0       	rcall	.+4      	; 0x54 <main>
 50:	08 c0       	rjmp	.+16     	; 0x62 <_exit>

00000052 <__bad_interrupt>:
 52:	d6 cf       	rjmp	.-84     	; 0x0 <__heap_end>

00000054 <main>:
char x[32];

int main(void)
{
 54:	cf e5       	ldi	r28, 0x5F	; 95
 56:	d2 e0       	ldi	r29, 0x02	; 2
 58:	de bf       	out	0x3e, r29	; 62
 5a:	cd bf       	out	0x3d, r28	; 61
return 0;
 5c:	80 e0       	ldi	r24, 0x00	; 0
 5e:	90 e0       	ldi	r25, 0x00	; 0
 60:	00 c0       	rjmp	.+0      	; 0x62 <_exit>

00000062 <_exit>:
 62:	ff cf       	rjmp	.-2      	; 0x62 <_exit>

Наблюдаем:

0000003e <__do_clear_bss>:

Что оно делает реально я не знаю. Потому как не знаю ассемблера AVR.

 

Забыл сказать. Все это в Debian/Lenny.

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


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

:01: Что-то сам не додумался дизасм всего проекта сделать... Ступил.

 

Спасибо за оперативный и подробный ответ.

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


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

:01: Что-то сам не додумался дизасм всего проекта сделать... Ступил.

 

Спасибо за оперативный и подробный ответ.

Бывает.

Наздоровье :)

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


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

После написания программ на arm с помощью gcc, было очень необычно для avr-gcc отсутствие явного загрузочного кода и явного lowlevelinit.
Ну, почитать описание на avr-libc надо было.

void low_level_init() __attribute__((__naked__)) __attribute__((section(".init3")));
void low_level_init()
{
}

. Загрузочный код да, автоматом, если не укажете свой.

А реализованно ли в этом коде забивание нулями bss секции. И где эти исходники посмотреть можно?
Искать исходники avr-libc. Включить генерацию листинга и убедиться.
И всегда ли при объявлении глобального массива элементов любого типа например он будет заполнен нулями?
Если компилятор соответствует стандарту С - то да.

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


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

Ну, почитать описание на avr-libc надо было.

void low_level_init() __attribute__((__naked__)) __attribute__((section(".init3")));
void low_level_init()
{
}

А ещё лучше так:

/*--  INIT_CODE(number)  --------------------------------------------------
*  Макрос для занесення коду в секції .init#number
*
*  Наприклад:
*  INIT_CODE(1)
*  {
*    MCUCR = (1 << SRE);
*    XMCRA = (4 << SRL0) | (0 << SRW00);
*    XMCRB = (1 << XMBK);
*  }
*
*  розподіл секцій для avr-gcc:
*  .init0  Start here after reset.
*  .init1
*  .init2  Clear __zero_reg__, set up stack pointer.
*  .init3
*  .init4  Initialize data and BSS.
*  .init5
*  .init6  C++ constructors.
*  .init7
*  .init8
*  .init9  Call main().
*
*/


#define INIT_CODE_N(_number_,_name_)\
    static void init##_name_ (void) __attribute__ ((section(".init" #_number_), naked, used));\
    static void init##_name_ (void)

#define _INIT_CODE(n,l) INIT_CODE_N(n,l)
#define INIT_CODE(_number_) _INIT_CODE(_number_,__LINE__)

xelax, avr-gcc позволяет иметь сколько угодно этих "low level init" - хоть по нескольку штук на файл (удобно - достаточно просто прилинковать модуль UART и он сам проинициализирует всё, что ему нужно), причём в разные места относительно работы запускалки - секции .init1, .init3, .init5, .init7, .init8 отданы пользователю. "функции" в секциях .init* не вызываются! они линкуются друг за дружкой без call/ret.

У меня довольно популярна секция .init5 - уже стек и все переменные проинициализированы, но конструкторы ещё не начали работать.

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


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

Использую .init5 для инициализации периферии контроллера (регистры) и .init8 для инициализации пользовательской части программы

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


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

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

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

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

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

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

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

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

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

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