|
Запись структуры во флэш. |
|
|
|
Nov 25 2014, 08:32
|
Профессионал
    
Группа: Участник
Сообщений: 1 778
Регистрация: 29-03-12
Пользователь №: 71 075

|
Я работаю с камнем EFM32TG842. У него есть сектор во флэше для записи данных пользователя - страница 512 байт. Я хочу записать туда свою структуру. Код struct sFlashParam { uint16_t customerID; uint32_t mainCounter; uint32_t CWcounter; uint8_t mode; uint8_t channel; uint8_t meter_type; …и так далее. } и потом пишу. Код WriteToFlash(0x0FE00000, (uint32_t*)&flashParam1); функция выглядит так Код void WriteToFlash(uint32_t address, uint32_t *data) { uint32_t *addr = (uint32_t *) address; //(uint32_t *)0x0FE00000; MSC_Init(); MSC_ErasePage(addr); MSC_WriteWord(addr, data, sizeof(data)); MSC_Deinit(); } вопрос как структура запишется? каждый член структуры в 32-битный регистр? и как мне считать структуру из флэша?
|
|
|
|
|
Nov 25 2014, 09:17
|
Местный
  
Группа: Участник
Сообщений: 356
Регистрация: 9-06-07
Пользователь №: 28 315

|
Скорее всего как в памяти отображается так и запишется. Со всеми "дырками" от выравнивания. Считывать из флеша надо будет как точно такую же структуру. ЗЫ: Исключение - если функция записит знает, что пишет структуру, знает, какую структуру и будет разбирать ее по полям и записывать каждое поле отдельно.  Изврат, но реализуемо. Тогда функция чтения должна заниматься обратным процессом. Считывать отдельные поля и запихивать их в структуру.
--------------------
Хорошую систему делают из стандартных блоков нестандартно мыслящие инженеры.
|
|
|
|
|
Nov 25 2014, 09:38
|
Профессионал
    
Группа: Участник
Сообщений: 1 778
Регистрация: 29-03-12
Пользователь №: 71 075

|
Цитата(Golikov A. @ Nov 25 2014, 15:18)  а вы запишите, считайте и узнаете  наверняка есть функция и ReadFromFlash функции записи-считывания я немного переделал и сейчас они выглядят так Код void WriteToFlash(uint32_t address, uint32_t *data, uint32_t size ) { uint32_t *addr = (uint32_t *) address; MSC_Init(); MSC_ErasePage(addr); MSC_WriteWord(addr, data, size); MSC_Deinit();
}
void ReadFromFlash(uint32_t offset, uint32_t *data, uint32_t size) { int i; uint32_t *addr; for (i = 0; i < size; i++ ) { addr = (uint32_t *)(offset + i*4); data[i] = *addr; } } и тестирую (предварительно записав данные в структуру ) Код WriteToFlash(0x0FE00000, (uint32_t*)&flashParam1, sizeof (struct sFlashParam1));
ReadFromFlash(0x0FE00000, (uint32_t*)&flashParam1, sizeof (struct sFlashParam1)); возвращает нули.
|
|
|
|
|
Nov 25 2014, 09:54
|
Гуру
     
Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136

|
Цитата(Jenya7 @ Nov 25 2014, 12:38)  Код void ReadFromFlash(uint32_t offset, uint32_t *data, uint32_t size) { int i; uint32_t *addr; for (i = 0; i < size; i++ ) { addr = (uint32_t *)(offset + i*4); data[i] = *addr; } } Под столом :-) А memcpy чем не угодил? Вообще-то данные из флеш читаются точно так же, как из ОЗУ. Советую просто сделать указатель на структуру во флеш и читать через него: Код struct mystruct* const ptr = (struct mystruct*)0x12345678; А ещё учите язык Си. Керниган и Ричи - хороший учебник.
|
|
|
|
|
Nov 25 2014, 10:06
|
Гуру
     
Группа: Участник
Сообщений: 2 219
Регистрация: 16-08-12
Из: Киров
Пользователь №: 73 143

|
Цитата(Jenya7 @ Nov 25 2014, 11:32)  У него есть сектор во флэше для записи данных пользователя - страница 512 байт. И что, прямо так и записывается, без всяких там разрешений записи во флеш, включения режимов записи, предварительного стирания сектора и т.п.?? Интересный камень, вернее, флешка у него интересная  ЗЫ. Если не пишется структура, попробуйте записать просто массив чисел, и посмотреть, записался или нет...
Сообщение отредактировал mantech - Nov 25 2014, 10:07
|
|
|
|
|
Nov 25 2014, 10:16
|
Гуру
     
Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454

|
Цитата И что, прямо так и записывается, без всяких там разрешений записи во флеш, включения режимов записи, предварительного стирания сектора и т.п.?? ну нет же... есть же MSC_Init(); MSC_ErasePage(addr); MSC_Deinit(); беспокоит MSC_WriteWord(addr, data, sizeof(data)); - запись слова, странное имя функции, ну да ладно... Цитата дебагер показывает корректные адреса в цикле. приращение 4 байта. ну если дебагер показывает то ладно... тогда можно не беспокоится... пусть вам еще дебагер покажет такие вещи Код int32_t a; sizeof(a); int32_t TotalK = 0;
for(int i=0;i<sizeof(a);i++) TotalK = i*4;
|
|
|
|
|
Nov 25 2014, 11:02
|
Профессионал
    
Группа: Участник
Сообщений: 1 778
Регистрация: 29-03-12
Пользователь №: 71 075

|
Цитата(Golikov A. @ Nov 25 2014, 16:16)  пусть вам еще дебагер покажет такие вещи Код int32_t a; sizeof(a); int32_t TotalK = 0;
for(int i=0;i<sizeof(a);i++) TotalK = i*4; я наверное туплю, но я не вижу здесь криминала.
|
|
|
|
|
Nov 25 2014, 11:22
|
Профессионал
    
Группа: Участник
Сообщений: 1 778
Регистрация: 29-03-12
Пользователь №: 71 075

|
сделал по совету scifi . Код memcpy(&flashParam1, 0x0FE00000, sizeof (struct sFlashParam1)); вроде как считывает корректные данные. значит и запись работает.
|
|
|
|
|
Nov 25 2014, 12:00
|
Гуру
     
Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136

|
Цитата(Jenya7 @ Nov 25 2014, 14:22)  Код memcpy(&flashParam1, 0x0FE00000, sizeof (struct sFlashParam1)); Вы будете смеяться, но это то же самое, что и Код flashParam1 = *(struct sFlashParam1*)0x0FE00000;
|
|
|
|
|
Nov 25 2014, 12:48
|
Профессионал
    
Группа: Участник
Сообщений: 1 778
Регистрация: 29-03-12
Пользователь №: 71 075

|
Цитата(Golikov A. @ Nov 25 2014, 17:39)  Код flashParam1 = *(struct sFlashParam1*)0x0FE00000; А это по стандарту? Это как-то подменяется на memcpy неявно? у меня тоже такой вопрос возник. посмотрел в листинг но там ассемблер ничего не понятно.
|
|
|
|
|
Nov 25 2014, 14:25
|
Знающий
   
Группа: Участник
Сообщений: 643
Регистрация: 29-05-09
Из: Германия
Пользователь №: 49 725

|
Цитата(Jenya7 @ Nov 25 2014, 10:32)  Я работаю с камнем EFM32TG842. У него есть сектор во флэше для записи данных пользователя - страница 512 байт. Я хочу записать туда свою структуру. Код void WriteToFlash(const uint32_t address, void const *data, uint32_t size) { size = 4 * ((size + 3)/4); // always divisable by 4 MSC_Init(); MSC_ErasePage((const uint32_t *)address); MSC_WriteWord((const uint32_t *)address, data, size); MSC_Deinit(); } Код WriteToFlash(USERDATA_BASE, &my_struct, sizeof(my_struct)); Не забудьте также разместить функции работы с флэш в ОЗУ (требование процессора). В библиотеке уже все подготовлено, но в среде разработки в скаттер-файле надо указать разместить секцию ram_code в ОЗУ. Для KEIL это будет модификация подсекции загрузки ОЗУ: Код RW_IRAM1 0x20000000 0x00004000 {; RW data *(ram_code, +First) ; flash erase/write functions .ANY (+RW +ZI) }
|
|
|
|
|
Nov 25 2014, 17:37
|
Знающий
   
Группа: Участник
Сообщений: 643
Регистрация: 29-05-09
Из: Германия
Пользователь №: 49 725

|
Цитата(Jenya7 @ Nov 25 2014, 16:43)  спасибо большое за ЦУ. а __attribute__ ((section(".ram"))) не поможет? вроде как это тоже указание на размещение функции в ram. Функции работы с флэшем в библиотеке для EFM32 уже объявлены и "сложены" в именованную секцию "ram_code", поэтому нужно секцию "ram_code" лишь как-то поместить в ОЗУ. Как написано в помощи к функции WriteWord Цитата The flash must be erased prior to writing a new word. This function must be run from RAM. Failure to execute this portion of the code in RAM will result in a hardfault. For IAR, Rowley and Codesourcery this will be achieved automatically. For Keil uVision 4 you must define a section called "ram_code" and place this manually in your project's scatter file. Кстати, коль мы о секциях заговорили. Вы можете разместить структуру напрямую в пользовательской странице и работать с ней в коде программы как с нормальной константой во flash: Код const MyType MyStruct __attribute__((section("MYDATA"), used)) = {<init fields>}; В скаттере надо указать, чтобы все константы секции были размещены в пользовательской странице, то есть добавить load region Код LR_IROM_SETS (0xFE00000) 0x200 {; User settings in the user ER_IROM_SETS (0x0FE00000) 0x200 {; flash page *(MYDATA) } } В итоге, можно иметь константы, объявленные в разных участках кода, разных файлах проекта, но принадлежащие одной и той же именованной секции, как это показано выше, и пользовать их как обычные константы. А компоновщик кинет все в нужную область флэша согласно указанию из скаттера. Затем можно, например, через коммуникационный протокол модифицировать все эти константы, настраивая таким образом приложение. Например, сменить адрес узла, и т.п. И не надо хранить "копии" настроек из флэш в ОЗУ: в конце концов ОЗУ в контроллерах всегда существенно меньше, чем флэш.
Сообщение отредактировал KnightIgor - Nov 25 2014, 17:40
|
|
|
|
|
Nov 25 2014, 22:43
|
Знающий
   
Группа: Участник
Сообщений: 643
Регистрация: 29-05-09
Из: Германия
Пользователь №: 49 725

|
Цитата(Golikov A. @ Nov 25 2014, 19:58)  Можно конечно их все объявить константами, но тогда будет не очень удобно обновлять параметры из меню пользователя или через внешний протокол... если это только константы, то да удобно. Если параметры во флэше, - а я бы назвал это настройками, - обновляются не по 10 раз в секунду, а в какие-либо ключевые моменты жизни приложения, после чего последнее пользуется результатами и делает свою работу, то почему же не удобно обновлять прямо во флэше? Например, коэффициенты коррекций и поправок в системе с ADC, и т.п. Ну, вначале, при калибровке, может и надо будет раз 20 перезаписать настройки, но потом они будут довольно долго неизменны. Или вот пример из нашей практики. Надо управлять светодиодами через ШИМ. Характеристка вход-выход выражается степенной функцией (гамма-коррекция). Если считать на лету каждый раз по формуле для нескольких каналов, можно перегрузить процессор. Можно работать и по таблице, но ее надо качать по каналу. Мы же меняем показатель (гамму) короткой командой, а процессор тут же единожды вычисляет и создает таблицу, которой потом и пользуется постоянно. Все во флэше.
|
|
|
|
|
Nov 26 2014, 04:40
|

Профессионал
    
Группа: Свой
Сообщений: 1 261
Регистрация: 14-05-09
Из: Челябинск
Пользователь №: 49 045

|
Цитата(scifi @ Nov 25 2014, 17:00)  Вы будете смеяться, но это то же самое, что и Код flashParam1 = *(struct sFlashParam1*)0x0FE00000; это совершенно разные вещи. так структуру объявлять не правильно, тем более для 32-х разрядного проца. Нужно выравнивать к 4-ём. Чтоб не париться над выравниванием лучше в структуре сначало объявить 32-х битные переменные ,потом 16-ти, затем 8-ми.
|
|
|
|
|
Nov 26 2014, 06:26
|
Гуру
     
Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454

|
да вот что-то получается что так наоборот даже более правильно чем через memcpy напрямую. Цитата то почему же не удобно обновлять прямо во флэше... ну то есть у вас в коде это константы и вы их изменить не можете из программы. И есть дополнительные функции которые просто меняют область флеши, фактически не думая что там лежит и тем самым обходят защиту const. В целом решение, проблему вижу только при изменении структуры настроек во время модификации кода, надо не забыть поправить ее в 2 местах. То есть и саму структуру и функции ее сохранения-модификации во флеше.
|
|
|
|
|
Nov 26 2014, 07:02
|
Профессионал
    
Группа: Участник
Сообщений: 1 778
Регистрация: 29-03-12
Пользователь №: 71 075

|
Цитата(juvf @ Nov 26 2014, 09:40)  это совершенно разные вещи.
так структуру объявлять не правильно, тем более для 32-х разрядного проца. Нужно выравнивать к 4-ём. Чтоб не париться над выравниванием лучше в структуре сначало объявить 32-х битные переменные ,потом 16-ти, затем 8-ми. как я понял если не указывать явно packed компайлер по дефолту делает padding. Цитата(KnightIgor @ Nov 25 2014, 22:37)  Функции работы с флэшем в библиотеке для EFM32 уже объявлены и "сложены" в именованную секцию "ram_code", поэтому нужно секцию "ram_code" лишь как-то поместить в ОЗУ. Как написано в помощи к функции WriteWord Кстати, коль мы о секциях заговорили. Вы можете разместить структуру напрямую в пользовательской странице и работать с ней в коде программы как с нормальной константой во flash: Код const MyType MyStruct __attribute__((section("MYDATA"), used)) = {<init fields>}; В скаттере надо указать, чтобы все константы секции были размещены в пользовательской странице, то есть добавить load region Код LR_IROM_SETS (0xFE00000) 0x200 {; User settings in the user ER_IROM_SETS (0x0FE00000) 0x200 {; flash page *(MYDATA) } } В итоге, можно иметь константы, объявленные в разных участках кода, разных файлах проекта, но принадлежащие одной и той же именованной секции, как это показано выше, и пользовать их как обычные константы. А компоновщик кинет все в нужную область флэша согласно указанию из скаттера. Затем можно, например, через коммуникационный протокол модифицировать все эти константы, настраивая таким образом приложение. Например, сменить адрес узла, и т.п. И не надо хранить "копии" настроек из флэш в ОЗУ: в конце концов ОЗУ в контроллерах всегда существенно меньше, чем флэш. Я пишу в Attolic TrueStudio и я честно говоря не нашел там скаттер файл.
|
|
|
|
|
Nov 26 2014, 07:25
|
Гуру
     
Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136

|
Цитата(Golikov A. @ Nov 26 2014, 09:26)  ну то есть у вас в коде это константы и вы их изменить не можете из программы. И есть дополнительные функции которые просто меняют область флеши, фактически не думая что там лежит и тем самым обходят защиту const. Если структура в флэш-памяти может меняться в процессе работы программы, её следует объявлять как const volatile. Цитата(Golikov A. @ Nov 26 2014, 09:26)  В целом решение, проблему вижу только при изменении структуры настроек во время модификации кода, надо не забыть поправить ее в 2 местах. То есть и саму структуру и функции ее сохранения-модификации во флеше. Эта проблема - вовсе не проблема. Для этого существует X Macro.
|
|
|
|
|
Nov 26 2014, 13:32
|
Профессионал
    
Группа: Участник
Сообщений: 1 778
Регистрация: 29-03-12
Пользователь №: 71 075

|
Цитата(KnightIgor @ Nov 26 2014, 14:34)  Однако способ управления размещением секций должен быть. Навскидку загуглил фразу "atollic truestudio linker script". Куча ссылок. нашел файл efm32_flash.ld CODE /* ***************************************************************************** ** ** File : efm32_flash.ld ** ** Abstract : Linker script for EFM32TG842F32 Device with ** 32KByte FLASH, 4KByte RAM ** ** Set heap size, stack size and stack location according ** to application requirements. ** ** Set memory bank area and size if external memory is used. ** ** Target : Energy Micro EFM32 ** ** Environment : Atollic TrueSTUDIO® ** ** Distribution: The file is distributed “as is,” without any warranty ** of any kind. ** ** ©Copyright Atollic AB. ** You may use this file as-is or modify it according to the needs of your ** project. This file may only be built (assembled or compiled and linked) ** using the Atollic TrueSTUDIO® product. The use of this file together ** with other tools than Atollic TrueSTUDIO® is not permitted. ** ***************************************************************************** */
/* Entry Point */ ENTRY(Reset_Handler)
/* Highest address of the user mode stack */ _estack = 0x20001000; /* end of 4K RAM */
/* Generate a link error if heap and stack don't fit into RAM */ _Min_Heap_Size = 0; /* required amount of heap */ _Min_Stack_Size = 0x80; /* required amount of stack */
/* Specify the memory areas */ MEMORY { FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 32K RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 4K MEMORY_B1 (rx) : ORIGIN = 0x60000000, LENGTH = 0K }
/* Define output sections */ SECTIONS { /* The startup code goes first into FLASH */ .isr_vector : { . = ALIGN(4); KEEP(*(.isr_vector)) /* Startup code */ . = ALIGN(4); } >FLASH
/* The program code and other data goes into FLASH */ .text : { . = ALIGN(4); *(.text) /* .text sections (code) */ *(.text*) /* .text* sections (code) */ *(.glue_7) /* glue arm to thumb code */ *(.glue_7t) /* glue thumb to arm code */ *(.eh_frame)
KEEP (*(.init)) KEEP (*(.fini))
. = ALIGN(4); _etext = .; /* define a global symbols at end of code */ } >FLASH
/* Constant data goes into FLASH */ .rodata : { . = ALIGN(4); *(.rodata) /* .rodata sections (constants, strings, etc.) */ *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ . = ALIGN(4); } >FLASH
.ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH .ARM : { __exidx_start = .; *(.ARM.exidx*) __exidx_end = .; } >FLASH
.preinit_array : { PROVIDE_HIDDEN (__preinit_array_start = .); KEEP (*(.preinit_array*)) PROVIDE_HIDDEN (__preinit_array_end = .); } >FLASH .init_array : { PROVIDE_HIDDEN (__init_array_start = .); KEEP (*(SORT(.init_array.*))) KEEP (*(.init_array*)) PROVIDE_HIDDEN (__init_array_end = .); } >FLASH .fini_array : { PROVIDE_HIDDEN (__fini_array_start = .); KEEP (*(SORT(.fini_array.*))) KEEP (*(.fini_array*)) PROVIDE_HIDDEN (__fini_array_end = .); } >FLASH
/* used by the startup to initialize data */ _sidata = LOADADDR(.data);
/* Initialized data sections goes into RAM, load LMA copy after code */ .data : { . = ALIGN(4); _sdata = .; /* create a global symbol at data start */ *(.data) /* .data sections */ *(.data*) /* .data* sections */
. = ALIGN(4); _edata = .; /* define a global symbol at data end */ } >RAM AT> FLASH
/* Uninitialized data section */ . = ALIGN(4); .bss : { /* This is used by the startup in order to initialize the .bss secion */ _sbss = .; /* define a global symbol at bss start */ __bss_start__ = _sbss; *(.bss) *(.bss*) *(COMMON)
. = ALIGN(4); _ebss = .; /* define a global symbol at bss end */ __bss_end__ = _ebss; } >RAM
/* User_heap_stack section, used to check that there is enough RAM left */ ._user_heap_stack : { . = ALIGN(4); PROVIDE ( end = . ); PROVIDE ( _end = . ); . = . + _Min_Heap_Size; . = . + _Min_Stack_Size; . = ALIGN(4); } >RAM
/* MEMORY_bank1 section, code must be located here explicitly */ /* Example: extern int foo(void) __attribute__ ((section (".mb1text"))); */ .memory_b1_text : { *(.mb1text) /* .mb1text sections (code) */ *(.mb1text*) /* .mb1text* sections (code) */ *(.mb1rodata) /* read-only data (constants) */ *(.mb1rodata*) } >MEMORY_B1
/* Remove information from the standard libraries */ /DISCARD/ : { libc.a ( * ) libm.a ( * ) libgcc.a ( * ) }
.ARM.attributes 0 : { *(.ARM.attributes) } }
только не знаю куда там вставлять. я как вы поняли не такой спец.
|
|
|
|
|
Nov 27 2014, 15:40
|
Знающий
   
Группа: Участник
Сообщений: 643
Регистрация: 29-05-09
Из: Германия
Пользователь №: 49 725

|
Цитата(Jenya7 @ Nov 26 2014, 15:32)  нашел файл efm32_flash.ld Я не спец по GCC. По аналогии с KEIL мне кажется, что надо так-то так: Код /* Uninitialized data section */ . = ALIGN(4); .bss : { /* This is used by the startup in order to initialize the .bss secion */ _sbss = .; /* define a global symbol at bss start */ __bss_start__ = _sbss; *(.bss) *(.bss*) *(COMMON) *(ram_code) /* <--------------------- */
. = ALIGN(4); _ebss = .; /* define a global symbol at bss end */ __bss_end__ = _ebss; } >RAM Хотя еще раз напомню цитату из помощи к EFM32 библиотеке, что, возможно, уже все делается автоматически. Посмотрите карту памяти и поищите ram_code по тексту.
Сообщение отредактировал KnightIgor - Nov 27 2014, 15:41
|
|
|
|
|
Nov 27 2014, 18:08
|

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

|
Нет, RAM-функции надо не в bss (это неинициализированные данные), а в data (инициализированные данные). (Потому что стартап-код bss просто заполняет нулями, а в data копирует их копию из флеша. Как-то так: Код .data : { . = ALIGN(4); _sdata = .; /* start of .data label (in RAM, VMA) */ *(.data) *(.data.*) *(.ram_code.*) /* <--------------------- */ } > RAM AT > FLASH
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
|
Nov 28 2014, 07:57
|

Местный
  
Группа: Свой
Сообщений: 243
Регистрация: 5-10-06
Из: Зеленоград
Пользователь №: 21 007

|
Цитата(Golikov A. @ Nov 25 2014, 15:39)  Код flashParam1 = *(struct sFlashParam1*)0x0FE00000; А это по стандарту? Это как-то подменяется на memcpy неявно? Это, товарищи, мы с вами бородатые стали слишком  Недавно тоже столкнулся с таким кодом - человек структуру просто приравнял к другой структуре. Я сказал ему исправить, но как ни странно, код оказался рабочим. Перечитывать пришлось стандарты языка C  Вроде как копирование структур через оператор '=' в std=c99 появилось. Удобная штука! =)
|
|
|
|
|
Nov 28 2014, 08:18
|
Знающий
   
Группа: Участник
Сообщений: 643
Регистрация: 29-05-09
Из: Германия
Пользователь №: 49 725

|
Цитата(Aaron @ Nov 28 2014, 09:57)  Это, товарищи, мы с вами бородатые стали слишком  Недавно тоже столкнулся с таким кодом - человек структуру просто приравнял к другой структуре. Я сказал ему исправить, но как ни странно, код оказался рабочим. Перечитывать пришлось стандарты языка C  Вроде как копирование структур через оператор '=' в std=c99 появилось. Удобная штука! =) А если глянуть в ассемблер, то при таком копировании используется memcpy(). Кстати, о C99. Он позволяет объявлять локальные массивы переменной длины внутри функции, в зависимости, скажем, от входного параметра: Код void func(size_t size) { char buffer[size]; ... } Под KEIL для этого используется malloc(). Так что нужно позаботиться о размере heap и полезно проверять: if (buffer) {...}. Правда, что делать, если buffer будет NULL, тоже не ясно. Hard Fault генерировать? Вообще, жаль, что malloc(), а не типа SP -= size. Интересно, как делает GCC?
|
|
|
|
|
Nov 28 2014, 09:53
|

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

|
Цитата(KnightIgor @ Nov 28 2014, 10:18)  А если глянуть в ассемблер, то при таком копировании используется memcpy(). Может использоваться. А может не использоваться. А может не использоваться даже там, где явно вызывается в исходнике. Зависит от степени продвинутости компилятора. Например, если затраты на вызов memcpy() окажутся больше, чем прямое копирование через регистры. Если компилятор знает, что скопировать нужно 4 байта - проще и быстрее их перекидать через регистры. Цитата(KnightIgor @ Nov 28 2014, 10:18)  Под KEIL для этого используется malloc(). Хм. забавно. Стандарт говорит (6.2.4) , что такой массив должен иметь automatic storage duration, в то время как созданные через malloc() объекты имеют allocated storage duration. С другой стороны, если компилятор сам в нужных местах вызывает malloc() и free() для такого объекта - вроде бы и требования для automatic storage duration выполняются. То есть решение неожиданное, но тем не менее не запрещенное. gcc размещает такой массив на стеке.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|