Hardfault при запуске CC2538 (Cortex m3), в __lib_init_array

Я пытаюсь перенести проект mbed-os (RTX RTOS) на CC2538 (ARM Cortex M3), который скомпилирован с использованием цепочки инструментов mbed-cli, которая объединяет arm-none-eabi-gcc. Когда я пытаюсь загрузить MCU, я зацикливаюсь на ошибке Hard Fault при запуске.

00202678 <__libc_init_array>:
202678:       b570            push    {r4, r5, r6, lr}
20267a:       4e0f            ldr     r6, [pc, #60]   ; (2026b8 <__libc_init_array+0x40>)
20267c:       4d0f            ldr     r5, [pc, #60]   ; (2026bc <__libc_init_array+0x44>)
20267e:       1b76            subs    r6, r6, r5
202680:       10b6            asrs    r6, r6, #2
202682:       bf18            it      ne
202684:       2400            movne   r4, #0
202686:       d005            beq.n   202694 <__libc_init_array+0x1c>
202688:       3401            adds    r4, #1
20268a:       f855 3b04       ldr.w   r3, [r5], #4
20268e:       4798            blx     r3
202690:       42a6            cmp     r6, r4
202692:       d1f9            bne.n   202688 <__libc_init_array+0x10>
202694:       4e0a            ldr     r6, [pc, #40]   ; (2026c0 <__libc_init_array+0x48>)
202696:       4d0b            ldr     r5, [pc, #44]   ; (2026c4 <__libc_init_array+0x4c>)
202698:       f004 fec2       bl      207420 <_etext>
20269c:       1b76            subs    r6, r6, r5
20269e:       10b6            asrs    r6, r6, #2
2026a0:       bf18            it      ne
2026a2:       2400            movne   r4, #0
2026a4:       d006            beq.n   2026b4 <__libc_init_array+0x3c>
2026a6:       3401            adds    r4, #1
2026a8:       f855 3b04       ldr.w   r3, [r5], #4
2026ac:       4798            blx     r3
2026ae:       42a6            cmp     r6, r4
2026b0:       d1f9            bne.n   2026a6 <__libc_init_array+0x2e>
2026b2:       bd70            pop     {r4, r5, r6, pc}
2026b4:       bd70            pop     {r4, r5, r6, pc}
2026b6:       bf00            nop

Я проследил поток кода, последний шаг ПК выполняется

 2026a4:       d006            beq.n   2026b4 <__libc_init_array+0x3c>

затем

 2026b4:       bd70            pop     {r4, r5, r6, pc}

в этот момент ПК получает значение 0, затем переходит на адрес 0x00000000 и вызывает
Ошибка жесткого сбоя.

после выполнения процессора

 202678:       b570            push    {r4, r5, r6, lr}

[register]
R0 =00000000
R1 =00000001
R2 =00000000
R3 =00000002
R4 =00000000
R5 =00000000
R6 =00000000
R7 =00000000
R8 =00000000
R9 =00000000
R10=00000000
R11=00000000
R12=00200F51
SP =200019F0
LR =00200A77
PC =0020267A
[memory]
200019b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
200019c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
200019d0: f0 09 00 20 00 00 00 00 00 00 00 00 04 0a 00 20
200019e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
200019f0: 00 00 00 00 00 00 00 00 00 00 00 00 77 0a 20 00
20001a00: 00 00 00 00 5d 0c 20 00 00 04 00 00 01 01 00 00

до выполнения процессора

2026b4:       bd70            pop     {r4, r5, r6, pc}

Отладочный дамп

[register]
R0 =00000000
R1 =00000001
R2 =00000000
R3 =00000002
R4 =00000000
R5 =00000000
R6 =00000000
R7 =00000000
R8 =00000000
R9 =00000000
R10=00000000
R11=00000000
R12=00200F51
SP =200019C0
LR =0020269D
PC =002026B4
[memory]
200019b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
200019c0: 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
200019d0: 00 00 00 00 9d 26 20 00 02 00 00 00 00 00 00 00
200019e0: 00 00 00 00 00 00 00 00 00 00 00 00 9d 26 20 00
200019f0: 00 00 00 00 00 00 00 00 00 00 00 00 77 0a 20 00
20001a00: 00 00 00 00 5d 0c 20 00 00 04 00 00 01 01 00 00

И если я вручную изменю StackPointer на 0x200019f0 когда команда поп-регистров выполняется в __libc_init_array.
и я обнаружил, что он успешно перейдет к main () в конце.
Кажется, проблема решается.
Мой вопрос заключается в том, почему управление стека происходит неправильно в __libc_init_array () ??
Я даже не могу найти исходный код реализации функции __libc_init_array () в рамках всего проекта mbed-os.


прикрепил файл .ld

MEMORY
{
FLASH_FW (rx) : ORIGIN = 0x00200000 + 0,
LENGTH = (0x00200000 + (((((0) << 0 | (512) << 4 | (32) << 16 | ((1) ? 0x01000000 : 0) | ((1) ? 0x02000000 : 0)) & 0x0000FFF0) >> 4) << 10) - 0x0000002C) - (0x00200000 + 0)
FLASH_CCA (RX) : ORIGIN = (0x00200000 + (((((0) << 0 | (512) << 4 | (32) << 16 | ((1) ? 0x01000000 : 0) | ((1) ? 0x02000000 : 0)) & 0x0000FFF0) >> 4) << 10) - 0x0000002C), LENGTH = 0x0000002C
NRSRAM (RWX) : ORIGIN = 0x20000000, LENGTH = 0
FRSRAM (RWX) : ORIGIN = (((((((0) << 0 | (512) << 4 | (32) << 16 | ((1) ? 0x01000000 : 0) | ((1) ? 0x02000000 : 0)) & 0x00FF0000) >> 16) << 10) - ((((((((0) << 0 | (512) << 4 | (32) << 16 | ((1) ? 0x01000000 : 0) | ((1) ? 0x02000000 : 0)) & 0x00FF0000) >> 16) << 10)) < (16384)) ? ((((((0) << 0 | (512) << 4 | (32) << 16 | ((1) ? 0x01000000 : 0) | ((1) ? 0x02000000 : 0)) & 0x00FF0000) >> 16) << 10)) : (16384))) ? 0x20000000 : 0x20004000), LENGTH = (((((0) << 0 | (512) << 4 | (32) << 16 | ((1) ? 0x01000000 : 0) | ((1) ? 0x02000000 : 0)) & 0x00FF0000) >> 16) << 10)
}

/* Linker script to place sections and symbol values. Should be used together
* with other linker script that defines memory regions FLASH and RAM.
* It references following symbols, which must be defined in code:
*   Reset_Handler : Entry of reset handler
*
* It defines following symbols, which code can use without definition:
*   __exidx_start
*   __exidx_end
*   __etext
*   __data_start__
*   __preinit_array_start
*   __preinit_array_end
*   __init_array_start
*   __init_array_end
*   __fini_array_start
*   __fini_array_end
*   __data_end__
*   __bss_start__
*   __bss_end__
*   __end__
*   end
*   __HeapLimit
*   __StackLimit
*   __StackTop
*   __stack
*/
ENTRY(flash_cca_lock_page)

SECTIONS
{
.text :
{
_text = .;
*(.vectors)
*(.text*)
*(.rodata*)
_etext = .;
} > FLASH_FW= 0
.socdata (NOLOAD) :
{
*(.udma_channel_control_table)
} > FRSRAM
.data : ALIGN(4)
{
_data = .;
*(.data*)
_edata = .;
} > FRSRAM AT > FLASH_FW
_ldata = LOADADDR(.data);
.ARM.exidx :
{
*(.ARM.exidx*)
} > FLASH_FW
.bss :
{
_bss = .;
*(.bss*)
*(COMMON)
_ebss = .;
} > FRSRAM

.heap :
{
__end__ = .;
end = __end__;
*(.heap*)
__HeapLimit = .;
} > RAM

.stack (NOLOAD) :
{
*(.stack)
} > FRSRAM
_heap = .;
_eheap = ORIGIN(FRSRAM) + LENGTH(FRSRAM);
.nrdata (NOLOAD) :
{
_nrdata = .;
*(.nrdata*)
_enrdata = .;
} > NRSRAM
.flashcca :
{
*(.flashcca)
} > FLASH_CCA
}

0

Решение

@ notlikethat прав, проблема в файле сценария компоновки, но основная причина не в перекрытии разделов. как я пост выше. в __libc_init_array ()

202678:       b570            push    {r4, r5, r6, lr}

в это время указатель стека указывает на 0x200019F0, но кое-как, когда поп операция указатель стека указывает на 0x200019C0, и это вызывает ошибку Hardfault. Я проследил поток кода, в __libc_init_array(), он перейдет в раздел <_init> в

 202698:       f004 fec2       bl      207420 <_etext>

который так выглядит в памяти

00207420 <_init>:
207420:       b5f8            push    {r3, r4, r5, r6, r7, lr}
207422:       bf00            nop

00207424 <_fini>:
207426:       b5f8            push    {r3, r4, r5, r6, r7, lr}
207428:       bf00            nop

Мне интересно, что эта функция вызывает указатель стека за счет, из-за <_init> В разделе показаны только инструкции push, но нет инструкции pop.
Я делаю больше веб-поиска о <_init> раздел, и подтвердите, что это не должно быть только 2 инструкции. и это осуществляется с помощью файла компоновщика.

В предыдущем файле компоновщика я не заботился о .init & .fini раздел.
А потом я сделал некоторые изменения, и это выглядит как

.text :
{
_text = .;
*(.vectors)
*(.text*)

KEEP(*(.init))
KEEP(*(.fini))

/* .ctors */
*crtbegin.o(.ctors)
*crtbegin?.o(.ctors)
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
*(SORT(.ctors.*))
*(.ctors)

/* .dtors */
*crtbegin.o(.dtors)
*crtbegin?.o(.dtors)
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
*(SORT(.dtors.*))
*(.dtors)

*(.rodata*)

KEEP(*(.eh_frame*))

_etext = .;
} > FLASH_FW= 0
.socdata (NOLOAD) :

После компиляции то <_init> & <Раздел _fini> изменился следующим образом.

00207040 <_init>:
207040:       b5f8            push    {r3, r4, r5, r6, r7, lr}
207042:       bf00            nop
207044:       bcf8            pop     {r3, r4, r5, r6, r7}
207046:       bc08            pop     {r3}
207048:       469e            mov     lr, r3
20704a:       4770            bx      lr

0020704c <_fini>:
20704c:       b5f8            push    {r3, r4, r5, r6, r7, lr}
20704e:       bf00            nop
207050:       bcf8            pop     {r3, r4, r5, r6, r7}
207052:       bc08            pop     {r3}
207054:       469e            mov     lr, r3
207056:       4770            bx      lr
207058:       6465626d        .word   0x6465626d
20705c:       73736120        .word   0x73736120
207060:       61747265        .word   0x61747265
207064:       6e6f6974        .word   0x6e6f6974
207068:       69616620        .word   0x69616620
20706c:       3a64656c        .word   0x3a64656c
207070:       2c732520        .word   0x2c732520
207074:       6c696620        .word   0x6c696620
207078:       25203a65        .word   0x25203a65

а затем прыгнуть в main() успешно.

0

Другие решения

Других решений пока нет …