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

 
 
 
Reply to this topicStart new topic
> STM32F4: странный эффект после Erase Sector Flash
k000858
сообщение Jun 19 2014, 06:06
Сообщение #1


Местный
***

Группа: Участник
Сообщений: 319
Регистрация: 31-01-12
Пользователь №: 69 978



Стираю определенный сектор, проверяю сектор - везде 0xFFFFFFFF (то есть чисто), перезапускаю контроллер (по питанию или дебаггером), проверяю сектор на чистоту - везде 0
Эффект проявляется в 1 из 5-30 случаев интерации цикла: включение, чтение, стирание, чтение, сброс.

Кто нибудь сталкивался с подобным?
Go to the top of the page
 
+Quote Post
scifi
сообщение Jun 19 2014, 06:53
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136



Осмелюсь предположить, что ваша программа сама записывает туда 0, вы просто этого не замечаете.
Go to the top of the page
 
+Quote Post
k000858
сообщение Jun 19 2014, 07:12
Сообщение #3


Местный
***

Группа: Участник
Сообщений: 319
Регистрация: 31-01-12
Пользователь №: 69 978



Цитата(scifi @ Jun 19 2014, 10:53) *
Осмелюсь предположить, что ваша программа сама записывает туда 0, вы просто этого не замечаете.

нет, ну всякое конечно возможно..
именно поэтому после стирания сектора проверяю сектор на чистоту. везде 0xFF
передергиваю питание - 0 0 0 0
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Jun 19 2014, 08:37
Сообщение #4


Гуру
******

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



Цитата(k000858 @ Jun 19 2014, 10:12) *
нет, ну всякое конечно возможно..
Дайте внешний сброс не снимая питания. Если ситуация повторится - сотрите, зажмите сброс, подключитесь отладчиком, поставьте точку останова в начале программы (в Reset_handler()), отпустите сброс и дальше по шагам.


--------------------
На любой вопрос даю любой ответ
"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
scifi
сообщение Jun 19 2014, 08:42
Сообщение #5


Гуру
******

Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136



Цитата(Сергей Борщ @ Jun 19 2014, 12:37) *
Дайте внешний сброс не снимая питания. Если ситуация повторится - сотрите, зажмите сброс, подключитесь отладчиком, поставьте точку останова в начале программы (в Reset_handler()), отпустите сброс и дальше по шагам.

Я обычно в самом начале программы для отладки пишу что-то такое:
Код
int volatile wait = 1;
while (wait);

Соответственно, программа начудить не может. После подключения отладчика выйти из цикла совсем не трудно.
Go to the top of the page
 
+Quote Post
k000858
сообщение Jun 19 2014, 08:49
Сообщение #6


Местный
***

Группа: Участник
Сообщений: 319
Регистрация: 31-01-12
Пользователь №: 69 978



Цитата(Сергей Борщ @ Jun 19 2014, 12:37) *
Дайте внешний сброс не снимая питания. Если ситуация повторится - сотрите, зажмите сброс, подключитесь отладчиком, поставьте точку останова в начале программы (в Reset_handler()), отпустите сброс и дальше по шагам.

Эффект проявляется как при сбросе по питанию, так и по внешнему сбросу.
Все бы ничего, но далеко не каждый раз срабатывает. Иногда приходится раз 30 ребутнуть до проявления эффекта. соответственно отладчиком шагать придется долго (
Go to the top of the page
 
+Quote Post
scifi
сообщение Jun 19 2014, 08:59
Сообщение #7


Гуру
******

Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136



Цитата(k000858 @ Jun 19 2014, 12:49) *
отладчиком шагать придется долго

Наверное, можно поставить Watchpoint на регистр FLASH_CR.
Go to the top of the page
 
+Quote Post
k000858
сообщение Jun 19 2014, 11:06
Сообщение #8


Местный
***

Группа: Участник
Сообщений: 319
Регистрация: 31-01-12
Пользователь №: 69 978



Итак. нашлась причина эффекта. как устранить пока не придумал.

В общем подробности работы со флэш: все операции производятся для эмуляции еепром в о флэш, расположенной в секторах 2 и 3. Сама прошивка укладывается в секторы 0 и 1.

в секторе 4 расположена секция, прописанная в скрипте линкера




Код
FLASHB1 (rx) : ORIGIN = 0x08010000, LENGTH = 8

     * The FLASH Bank1.
     * The C or assembly source must explicitly place the code
     * or data there using the "section" attribute.
     */
    .b1text :
    {
        *(.b1text)                   /* remaining code */
        *(.b1rodata)                 /* read-only data (constants) */
        *(.b1rodata.*)
    } >FLASHB1


в этой секции располагается константа uint8_t data_in_flash[8] __attribute__((section(".b1rodata"))) не спрашивайте зачем. так надо.

дак вот именно расположение этой константы каким то образом "портит" содержимое секторов 2 и 3 где эмулируется еепром. отсюда все глюки: появление 0 после резета и тд.

По мап файлу видно, что ничего никуда не наползает, все находится в своих местах. как константа в 4м секторе флэш влияет на данные из 2 и 3 секторов хоть убей не понимаю.

Быть может у кого нибудь есть мысли ???
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Jun 19 2014, 11:13
Сообщение #9


Гуру
******

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



Может отладчик при запуске переписывает? Скажем, заполняет свободное пространство между секторами 0,1 и 4. Как в скрипте описана область 2 и 3 секторов?


--------------------
На любой вопрос даю любой ответ
"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
k000858
сообщение Jun 19 2014, 11:18
Сообщение #10


Местный
***

Группа: Участник
Сообщений: 319
Регистрация: 31-01-12
Пользователь №: 69 978



Цитата(Сергей Борщ @ Jun 19 2014, 15:13) *
Может отладчик при запуске переписывает? Скажем, заполняет свободное пространство между секторами 0,1 и 4. Как в скрипте описана область 2 и 3 секторов?

область 2 и 3 равна как и 0 1 простая програм флэш

CODE
MEMORY
{
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K
CCMRAM (xrw) : ORIGIN = 0x10000000, LENGTH = 64K
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 64K
FLASHB1 (rx) : ORIGIN = 0x08010000, LENGTH = 64K
EXTMEMB0 (rx) : ORIGIN = 0x00000000, LENGTH = 0
EXTMEMB1 (rx) : ORIGIN = 0x00000000, LENGTH = 0
EXTMEMB2 (rx) : ORIGIN = 0x00000000, LENGTH = 0
EXTMEMB3 (rx) : ORIGIN = 0x00000000, LENGTH = 0
MEMORY_ARRAY (xrw) : ORIGIN = 0x20002000, LENGTH = 32
}

/*
* Default linker script for STM32Fxxx.
*/

/*
* The '__stack' definition is required by crt0, do not remove it.
*/
__stack = ORIGIN(RAM) + LENGTH(RAM);

_estack = __stack; /* STM specific definition */

/*
* Default stack sizes.
* These are used by the startup in order to allocate stacks
* for the different modes.
*/

__Main_Stack_Size = 1024;

PROVIDE ( _Main_Stack_Size = __Main_Stack_Size );

__Main_Stack_Limit = __stack - __Main_Stack_Size;

/*"PROVIDE" allows to easily override these values from an object file or the command line. */
PROVIDE ( _Main_Stack_Limit = __Main_Stack_Limit );

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

/*
* Default heap definitions.
* The heap start immediately after the last statically allocated
* .sbss/.noinit section, and extends up to the main stack limit.
*/
PROVIDE ( _Heap_Begin = _end_noinit );
PROVIDE ( _Heap_Limit = __stack - _Main_Stack_Size );

/*
* The entry point is informative, for debuggers and simulators,
* since the Cortex-M vector points to it anyway.
*/
ENTRY(Reset_Handler)


/* Sections Definitions */

SECTIONS
{
/*
* For Cortex-M 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)) /* Interrupt vectors */

/*
* This section is here for convenience, to store the
* startup code at the beginning of the flash area, hoping that
* this will increase the readability of the listing.
*/
*(.after_vectors .after_vectors.*) /* Startup code and ISR */

. = ALIGN(4);
} >FLASH

._inits :
{
. = ALIGN(4);

/*
* These are the old initialisation sections, intended to contain
* naked code, with the prologue/epilogue added by crti.o/crtn.o
* when linking with startup files. The standalone startup code
* currently does not run these, better use the init arrays below.
*/
KEEP(*(.init))
KEEP(*(.fini))

. = ALIGN(4);

/*
* The preinit code, i.e. an array of pointers to initialisation
* functions to be performed before constructors.
*/
PROVIDE_HIDDEN (__preinit_array_start = .);

/*
* Used to run the SystemInit() before anything else.
*/
KEEP(*(.preinit_array_sysinit .preinit_array_sysinit.*))

/*
* Used for other platform inits.
*/
KEEP(*(.preinit_array_platform .preinit_array_platform.*))

/*
* The application inits. If you need to enforce some order in
* execution, create new sections, as before.
*/
KEEP(*(.preinit_array .preinit_array.*))

PROVIDE_HIDDEN (__preinit_array_end = .);

. = ALIGN(4);

/*
* The init code, i.e. an array of pointers to static constructors.
*/
PROVIDE_HIDDEN (__init_array_start = .);
KEEP(*(SORT(.init_array.*)))
KEEP(*(.init_array))
PROVIDE_HIDDEN (__init_array_end = .);

. = ALIGN(4);

/*
* The fini code, i.e. an array of pointers to static destructors.
*/
PROVIDE_HIDDEN (__fini_array_start = .);
KEEP(*(SORT(.fini_array.*)))
KEEP(*(.fini_array))
PROVIDE_HIDDEN (__fini_array_end = .);
. = ALIGN(4);

} >FLASH

/*
* For some STRx devices, the beginning of the startup code
* is stored in the .flashtext section, which goes to FLASH.
*/
.flashtext :
{
. = ALIGN(4);
*(.flashtext .flashtext.*) /* Startup code */
. = ALIGN(4);
} >FLASH


/*
* The program code is stored in the .text section,
* which goes to FLASH.
*/
.text :
{
. = ALIGN(4);

*(.text .text.*) /* all remaining code */

*(.rodata .rodata.*) /* read-only data (constants) */

KEEP(*(.eh_frame*))

/*
* Stub sections generated by the linker, to glue together
* ARM and Thumb code. .glue_7 is used for ARM code calling
* Thumb code, and .glue_7t is used for Thumb code calling
* ARM code. Apparently always generated by the linker, for some
* architectures, so better leave them here.
*/
*(.glue_7)
*(.glue_7t)

} >FLASH

/* ARM magic sections */
.ARM.extab :
{
*(.ARM.extab* .gnu.linkonce.armextab.*)
} > FLASH

__exidx_start = .;
.ARM.exidx :
{
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
} > FLASH
__exidx_end = .;

. = ALIGN(4);
_etext = .;

/*
* This address is used by the startup code to
* initialise the .data section.
*/
_sidata = _etext;

/* MEMORY_ARRAY */
.ROarraySection :
{
*(.ROarraySection .ROarraySection.*)
} >MEMORY_ARRAY


/*
* The initialised 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 code to initialise the .data section */
_sdata = .; /* STM specific definition */
__data_start__ = .;

*(vtable)

/* Exclude rdimon command line, to avoid loosing command line */
*(EXCLUDE_FILE (*rdimon-crt0.o) .data .data.*)

. = ALIGN(4);

/* This is used by the startup code to initialise the .data section */
_edata = .; /* STM specific definition */
__data_end__ = .;

} >RAM


/*
* The uninitialised data section.
*/
.bss :
{
. = ALIGN(4);

/* Moved outside the initialised area */
*rdimon-crt0.o(.data)

. = ALIGN(4);
__bss_start__ = .; /* standard newlib definition */
_sbss = .; /* STM specific definition */

*(.bss .bss.*)
*(COMMON)

. = ALIGN(4);
__bss_end__ = .; /* standard newlib definition */
_ebss = .; /* STM specific definition */
} >RAM

.noinit (NOLOAD):
{
. = ALIGN(4);
_noinit = .;

*(.noinit .noinit.*)

. = ALIGN(4);
_end_noinit = .;
} > RAM

/* Mandatory to be word aligned, _sbrk assumes this */
PROVIDE ( end = _end_noinit ); /* was _ebss */
PROVIDE ( _end = _end_noinit );
PROVIDE ( __end = _end_noinit );
PROVIDE ( __end__ = _end_noinit );

/*
* Used for validation only, do not allocate anything here!
*
* This is just to check that there is enough RAM left for the Main
* stack. It should generate an error if it's full.
*/
._check_stack :
{
. = ALIGN(4);

. = . + _Minimum_Stack_Size;

. = ALIGN(4);
} >RAM

.bss_CCMRAM : ALIGN(4)
{
*(.bss.CCMRAM .bss.CCMRAM.*)
} > CCMRAM

/*
* The FLASH Bank1.
* The C or assembly source must explicitly place the code
* or data there using the "section" attribute.
*/
.b1text :
{
*(.b1text) /* remaining code */
*(.b1rodata) /* read-only data (constants) */
*(.b1rodata.*)
} >FLASHB1

/*
* The EXTMEM.
* The C or assembly source must explicitly place the code or data there
* using the "section" attribute.
*/

/* EXTMEM Bank0 */
.eb0text :
{
*(.eb0text) /* remaining code */
*(.eb0rodata) /* read-only data (constants) */
*(.eb0rodata.*)
} >EXTMEMB0

/* EXTMEM Bank1 */
.eb1text :
{
*(.eb1text) /* remaining code */
*(.eb1rodata) /* read-only data (constants) */
*(.eb1rodata.*)
} >EXTMEMB1

/* EXTMEM Bank2 */
.eb2text :
{
*(.eb2text) /* remaining code */
*(.eb2rodata) /* read-only data (constants) */
*(.eb2rodata.*)
} >EXTMEMB2

/* EXTMEM Bank0 */
.eb3text :
{
*(.eb3text) /* remaining code */
*(.eb3rodata) /* read-only data (constants) */
*(.eb3rodata.*)
} >EXTMEMB3



/* After that there are only debugging sections. */

/* This removes 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) }
}


Сообщение отредактировал IgorKossak - Jun 19 2014, 14:40
Причина редактирования: [codebox] для длинного кода, [code] - для короткого!!!
Go to the top of the page
 
+Quote Post
scifi
сообщение Jun 19 2014, 11:36
Сообщение #11


Гуру
******

Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136



Цитата(Сергей Борщ @ Jun 19 2014, 15:13) *
Может отладчик при запуске переписывает? Скажем, заполняет свободное пространство между секторами 0,1 и 4.

Очень похоже.

Цитата(Сергей Борщ @ Jun 19 2014, 15:13) *
Как в скрипте описана область 2 и 3 секторов?

Я бы по-другому вопрос поставил.
Запустите отладчик без заливки прошивки. Посмотрите содержимое секторов 2, 3.
Запустите отладчик с заливкой прошивки. Посмотрите содержимое секторов 2, 3. Почувствуйте разницу.
Go to the top of the page
 
+Quote Post
k000858
сообщение Jun 20 2014, 04:20
Сообщение #12


Местный
***

Группа: Участник
Сообщений: 319
Регистрация: 31-01-12
Пользователь №: 69 978



Вчера чуть голова не вспухла от таких выкрутасов. Сегодня со свежей головой сделал так:
- очистил флэш
- отключил эмуляцию еепром (т.е. 2-3 сектора вообще не юзаются)
- руками через ST-Link utility записал во 2й сектор пару байт
- залил проект (в котором размещается переменная в 4м секторе).
в результате в 2-3 секторах 0xFF - т.е. действительно дебагер зачистил при заливке прошивки эти сектора.
а нолики там действительно появлялись при нарушенной работе эмуляции еепром

ну в общем тему можно считать раскрытой, всем спасибо за участие.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Jun 20 2014, 07:16
Сообщение #13


Гуру
******

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



Цитата(k000858 @ Jun 19 2014, 14:18) *
область 2 и 3 равно как и 0, 1 - простая програм флэш
Я не увидел специально зарезервированной под сектора 2 и 3 области. Если я достаточно внимательно просмотрел ваш скрипт, то в один прекрсный момент ваша программа может увеличиться настолько, что залезет в сектор 2, компилятор это молча съест, а вы получите совершенно неожиданное падение программы без очевидных причин. То есть надо бы выделить отдельный регион и разместить там соответствующую секцию. Это позволит вам добавляя к описанию секции (NOLOAD) запретить отладчику стирать и загружать в эту секцию начальные значения и в то же время убрав (NOLOAD) получить образ для начальной прошивки на этапе производства.


--------------------
На любой вопрос даю любой ответ
"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
k000858
сообщение Jun 20 2014, 09:55
Сообщение #14


Местный
***

Группа: Участник
Сообщений: 319
Регистрация: 31-01-12
Пользователь №: 69 978



Цитата(Сергей Борщ @ Jun 20 2014, 11:16) *
в один прекрсный момент ваша программа может увеличиться настолько, что залезет в сектор 2, компилятор это молча съест, а вы получите совершенно неожиданное падение программы без очевидных причин.

да, FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 64K ограничил до 32K (это на время отладки делал больше).


Цитата(Сергей Борщ @ Jun 20 2014, 11:16) *
То есть надо бы выделить отдельный регион и разместить там соответствующую секцию. Это позволит вам добавляя к описанию секции (NOLOAD) запретить отладчику стирать и загружать в эту секцию начальные значения и в то же время убрав (NOLOAD) получить образ для начальной прошивки на этапе производства.

регион
FLASHB1 (rx) : ORIGIN = 0x08010000, LENGTH = 64K
Код
    /*
     * The FLASH Bank1.
     * The C or assembly source must explicitly place the code
     * or data there using the "section" attribute.
     */
    .b1text :
    {
        *(.b1text)                   /* remaining code */
        *(.b1rodata)                 /* read-only data (constants) */
        *(.b1rodata.*)
    } >FLASHB1

достаточно сделать так?
Код
    .b1text (NOLOAD):
    {
        *(.b1text)                   /* remaining code */
        *(.b1rodata)                 /* read-only data (constants) */
        *(.b1rodata.*)
    } >FLASHB1


Сообщение отредактировал IgorKossak - Jun 20 2014, 10:41
Причина редактирования: [codebox] для длинного кода, [code] - для короткого!!!
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Jun 20 2014, 10:18
Сообщение #15


Гуру
******

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



Цитата(k000858 @ Jun 20 2014, 12:55) *
достаточно сделать так?
Да, при этом отладчик не будет загружать секцию b1text. Но вам нужно это сделать для секции, в которой эмулируется eeprom.


--------------------
На любой вопрос даю любой ответ
"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 - 11:30
Рейтинг@Mail.ru


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