реклама на сайте
подробности

 
 
> Проблема с константами в классе., В iar всё работает а в GCC нет...
inco
сообщение May 19 2010, 11:57
Сообщение #1


Частый гость
**

Группа: Свой
Сообщений: 161
Регистрация: 26-08-05
Из: Российская Империя
Пользователь №: 7 984



Есть некий базовый класс:

class uart {
protected:
const uint8_t num;
const uint8_t channel;
volatile uint32_t time;
uint8_t rxCount;
uint8_t echoMode;
__uartState state;
uint32_t tx_pointer;
uint32_t rx_pointer;
uint32_t size;
uint32_t txSize;
uint8_t rxEchoSize;
uint8_t error[2];
uint16_t crc;
public:
uart(const uint8_t n, const uint8_t c) : num(n), channel( c) { // Конструктор
time = tx_pointer = rx_pointer = size = 0;
error[0] = error[1] = 0;
};
...

есть от него наследник:

class mco_uart : public uart {
public:
uint8_t buf[2][MCO_BUFF_SIZE];
mco_uart(const uint8_t n, const uint8_t c) : uart (n, c) {}; // Конструктор
...

создаю экземпляры класса:

mco_uart extUart[EXTUART_NUM] = {
mco_uart(0, 4 << 4), mco_uart(0, 5 << 4), mco_uart(0, 6 << 4), mco_uart(0, 7 << 4),
mco_uart(1, 4 << 4), mco_uart(1, 5 << 4), mco_uart(1, 6 << 4), mco_uart(0, 1 << 4),
mco_uart(0, 2 << 4), mco_uart(0, 3 << 4), mco_uart(1, 0 << 4), mco_uart(1, 1 << 4),
mco_uart(1, 2 << 4), mco_uart(1, 3 << 4)
};

В результате переменные num и channel равны 0.
В иаре всё работает то есть значения переменным присваивается правильно, а в gcc присваивания нет.
Что я делаю не так? На плюсах пишу первый раз, до этого писал только на чистом C. Хочется перейти на gcc и не получается!
Компилятор от клёна kgp_arm_eabi_20100509
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
inco
сообщение May 19 2010, 16:13
Сообщение #2


Частый гость
**

Группа: Свой
Сообщений: 161
Регистрация: 26-08-05
Из: Российская Империя
Пользователь №: 7 984



Спасибо за информацию! Буду переваривать! Пока ничего не понял про конструкторы!

Объекты да глобальные.

По результатам отпишусь. Проверю только завтра на работе.

На всякий случай привожу свой скрипт линкера:

__Stack_Size = 1024 ;

PROVIDE ( _Stack_Size = __Stack_Size );

__Stack_Init = _estack - __Stack_Size;

/*"PROVIDE" allows to easily override these values from an object file or the commmand line.*/
PROVIDE ( _Stack_Init = __Stack_Init );

/*
There will be a link error if there is not this amount of RAM free at the end.
*/
_Minimum_Stack_Size = 0x100;


/* include the memory spaces definitions sub-script */
/*
Linker subscript for STM32F10x definitions with 512K Flash and 64K RAM */

/* Memory Spaces Definitions */

MEMORY
{
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 256K
SRAM (rwx) : ORIGIN = 0x20000000, LENGTH = 48K
}
/* higher address of the user mode stack */
_estack = 0x2000c000;



/* include the sections management sub-script for FLASH mode */

/* Sections Definitions */

SECTIONS
{
/* for Cortex devices, the beginning of the startup code is stored in the .isr_vector section, which goes to FLASH */
.isr_vector :
{
. = ALIGN(4);
KEEP(*(.isr_vector)) /* Startup code */
. = ALIGN(4);
} >SRAM

/* the program code is stored in the .text section, which goes to Flash */
.text :
{
. = ALIGN(4);
*(.text .text.* .gnu.linkonce.t.*)
*(.plt)
*(.gnu.warning)
*(.glue_7t) *(.glue_7) *(.vfp11_veneer)
*(.ARM.extab* .gnu.linkonce.armextab.*)
*(.gcc_except_table)
} >SRAM

.checksum 0x20005ffe :
{
. = ALIGN(2);
KEEP(*(.checksum)) /* Checksum code */
} >SRAM

.eh_frame_hdr : ALIGN (4)
{
KEEP (*(.eh_frame_hdr))
} >SRAM
.eh_frame : ALIGN (4)
{
KEEP (*(.eh_frame))
} >SRAM
/* .ARM.exidx is sorted, so has to go in its own output section. */
__exidx_start = .;
.ARM.exidx :
{
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
} >SRAM
__exidx_end = .;

.rodata : ALIGN (4)
{
*(.rodata .rodata.* .gnu.linkonce.r.*)

. = ALIGN(4);
KEEP(*(.init))

. = ALIGN(4);
__preinit_array_start = .;
KEEP (*(.preinit_array))
__preinit_array_end = .;

. = ALIGN(4);
__init_array_start = .;
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array))
__init_array_end = .;

. = ALIGN(4);
KEEP(*(.fini))

. = ALIGN(4);
__fini_array_start = .;
KEEP (*(.fini_array))
KEEP (*(SORT(.fini_array.*)))
__fini_array_end = .;

. = ALIGN(4);
KEEP (*crtbegin.o(.ctors))
KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*crtend.o(.ctors))

. = ALIGN(4);
KEEP (*crtbegin.o(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*crtend.o(.dtors))

. = ALIGN(4);
_etext = .;
/* This is used by the startup in order to initialize the .data secion */
_sidata = _etext;
} >SRAM

/* This is the initialized data section
The program executes knowing that the data is in the RAM
but the loader puts the initial values in the FLASH (inidata).
It is one task of the startup to copy the initial values from FLASH to RAM. */
.data : AT ( _sidata )
{
. = ALIGN(4);
/* This is used by the startup in order to initialize the .data secion */
_sdata = . ;
KEEP(*(.jcr))
*(.got.plt) *(.got)
*(.shdata)
*(.data .data.* .gnu.linkonce.d.*)

. = ALIGN(4);
/* This is used by the startup in order to initialize the .data secion */
_edata = . ;
} >SRAM

/* This is the uninitialized data section */
.bss :
{
. = ALIGN(4);
/* This is used by the startup in order to initialize the .bss secion */
_sbss = .;
*(.shbss)
*(.bss .bss.* .gnu.linkonce.b.*)
*(COMMON)
. = ALIGN(4);
/* This is used by the startup in order to initialize the .bss secion */
_ebss = . ;
} >SRAM

PROVIDE ( end = _ebss );
PROVIDE ( _end = _ebss );

/* This is the user stack section
This is just to check that there is enough RAM left for the User mode stack
It should generate an error if it's full. */
._usrstack :
{
. = ALIGN(4);
_susrstack = . ;
. = . + _Minimum_Stack_Size ;
. = ALIGN(4);
_eusrstack = . ;
} >SRAM


/* after that it's only debugging information. */

/* remove the debugging information from the standard libraries */
DISCARD :
{
libc.a ( * )
libm.a ( * )
libgcc.a ( * )
}

/* 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) }
/* SGI/MIPS DWARF 2 extensions */
.debug_weaknames 0 : { *(.debug_weaknames) }
.debug_funcnames 0 : { *(.debug_funcnames) }
.debug_typenames 0 : { *(.debug_typenames) }
.debug_varnames 0 : { *(.debug_varnames) }

note.gnu.arm.ident 0 : { KEEP (*(.note.gnu.arm.ident)) }
.ARM.attributes 0 : { KEEP (*(.ARM.attributes)) }
/DISCARD/ : { *(.note.GNU-stack) }
}

Стартап брал стандартный из библиотеки stm32 версии 3.2
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение May 19 2010, 18:31
Сообщение #3


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Цитата(inco @ May 19 2010, 22:13) *
Стартап брал стандартный из библиотеки stm32 версии 3.2


Этот стартап совершенно точно не вызывает конструкторы глобальных объектов.
Пример рабочего стартапа и линкерного скрипта для C++ можете посмотреть вот в этом примере из scmRTOS.
Проверено с kgp и codesourcery.


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
inco
сообщение May 20 2010, 06:15
Сообщение #4


Частый гость
**

Группа: Свой
Сообщений: 161
Регистрация: 26-08-05
Из: Российская Империя
Пользователь №: 7 984



Спасибо за помощь!!!

Всё получилось! Собрал гибрида стартапа из scmRtos и других примеров под себя и переделал скрипт линкера. Теперь вроде всё на месте, конструкторы работают. Вот только не понятно, как это всё работает, где бы про это почитать?

Интересует как происходит процесс инициализации конструкторов в деталях. Если со стартом сишной программы всё понятно, то с плюсами получается пробел в понимании. Вообще где почитать чем отличается инициализация сишной программы от плюсовой? Не люблю чего-то не понимать.

И ещё попутно вопрос по этой строке:

uart(const uint8_t n, const uint8_t c) : num(n), channel( c) { // Конструктор

параметры после двоеточия num(n), channel( c) не понимаю.
То есть, что происходит смысл понятен, присваивается значение константам, но вот как до этого додуматься не понятно! Я просто нашел этот способ инициализации констант в инете, а где про это почитать не нашел. Вроде по плюсам там должен быть предок а не переменные?!

Если вопросы глупые прошу сильно не пинать, на плюсах первый раз решил написать прогу.
До этого всё больше на чистом си. А теперь понравилось! Оказывается такая вещь... smile.gif
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение May 20 2010, 10:44
Сообщение #5


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Цитата(inco @ May 20 2010, 12:15) *
Всё получилось!

Аминьsmile.gif
Цитата
Интересует как происходит процесс инициализации конструкторов в деталях.

При помощи вызова оныхsmile.gif Аналогия с си - прямая. Если в си есть статическая переменная, то она инициализируется в стартапе. Если в C++ есть глобальный объект, то он точно так же инициализируется в стартапе. За инициализацию отвечает конструктор. Поэтому он вызывается из стартапа.
Цитата
Вообще где почитать

Читать естественно "Язык программирования С++", Бьерн Страуструп. Третье издание.


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение May 20 2010, 19:43
Сообщение #6


Гуру
******

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



Цитата(AHTOXA @ May 20 2010, 13:44) *
При помощи вызова оныхsmile.gif Аналогия с си - прямая. Если в си есть статическая переменная, то она инициализируется в стартапе. Если в C++ есть глобальный объект, то он точно так же инициализируется в стартапе. За инициализацию отвечает конструктор. Поэтому он вызывается из стартапа.
Более "на пальцах": Указатели на конструкторы помещаются в секцию .ctors, а код в стартапе проходит эту секцию, вызывая функции по считанному указателю. Если указатель равен нулю - баста. "Ловкость рук и никакого мошенничества".

Можно в скрипте линкера отсортировать эти указатели по именам объектов или именам файлов, обеспечив некоторый определенный порядок вызова конструкторов, но Страуструп такого не обещал.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
inco
сообщение May 20 2010, 20:10
Сообщение #7


Частый гость
**

Группа: Свой
Сообщений: 161
Регистрация: 26-08-05
Из: Российская Империя
Пользователь №: 7 984



Спасибо просветили! Скачал третье издание Страуструпа, все непонятности там нашёл! Да! Мир сильно изменился за это время. Тот что у меня на полке был (второе издание от 1993 года) там этого не было! Теперь на счёт языка всё стало ясно!

Теперь возникла другая проблема. Опять где-то, что-то не склеилось. В озу программа заработала полностью, а вот в пзу не хочет. Линкер разместил какие-то константы по адресу озу и J-Flash ARM не хочет шить пзу говорит недопустимый сегмент. Посмотрел мап файл, да действительно он туда распределил секцию дата:
.data 0x20000000 0x18
0x20000000 . = ALIGN (0x4)
0x20000000 _sdata = .
Вот только какого хрена она попадает в бинарный файл (который из-за этого получается размером с пол гиктара) пока не пойму. С кодом для озу при этом всё в порядке и бинарник размером 13К.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение May 20 2010, 20:49
Сообщение #8


Гуру
******

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



Цитата(inco @ May 20 2010, 23:10) *
Линкер разместил какие-то константы по адресу озу и J-Flash ARM не хочет шить пзу говорит недопустимый сегмент. Посмотрел мап файл, да действительно он туда распределил секцию дата:
.data 0x20000000 0x18
0x20000000 . = ALIGN (0x4)
0x20000000 _sdata = .
Вот только какого хрена она попадает в бинарный файл (который из-за этого получается размером с пол гиктара) пока не пойму.
Можно предположить, что некорректно написан скрипт линкера. Дело в том, что по стандартам gcc секция .data - инициализированные константы. Для упрощения процесса инициализации копия всех инициализированных значений хранится во флеше и при старте программы просто "тупо копируется" в ОЗУ. Для корректного выполнения этой операции скрипт линкера должен выглядеть примерно так:
Код
  /* .data section which is used for initialized data */
  .data : /* place init values immediatly after .text section */
  {
    _data = .;
    *(.ramfunc*)
    
    *(.data*)

    _edata = .;
    _data_image = LOADADDR(.data);

    PROVIDE (edata = .);
  } > RAM  AT > ROM
То есть разместить выходную секцию .data в регион RAM (Virtual Memory Address, VMA), но их значения положить в регион ROM (в Loadable Memory Address, LMA). В вашем скрипте магические слова "AT > ROM" скорее всего отсутствуют, и начальные значения остаются на своих реальных адресах.

P.S. И старайтесь оформлять исходники используя кнопку


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post



Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 21st July 2025 - 23:51
Рейтинг@Mail.ru


Страница сгенерированна за 0.01498 секунд с 7
ELECTRONIX ©2004-2016