|
Запись структуры во флэш. |
|
|
|
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
|
|
|