Jump to content

    
Sign in to follow this  
xelax

bss и avr-gcc

Recommended Posts

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

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

 

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

Share this post


Link to post
Share on other sites
После написания программ на 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.

Share this post


Link to post
Share on other sites
:01: Что-то сам не додумался дизасм всего проекта сделать... Ступил.

 

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

Бывает.

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

Share this post


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

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

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

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

Share this post


Link to post
Share on other sites
Ну, почитать описание на 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 - уже стек и все переменные проинициализированы, но конструкторы ещё не начали работать.

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this