Cortex M33 отсутствует таблица векторов

Я хочу протестировать свой проект ARM в QEMU, используя полухостинг. Первоначально я собирал для процессоров Cortex A7 и A9, и у меня не было проблем с запуском моего кода, однако теперь, когда я переключился на CM33 (и плату CM33), он сразу ломается:

C:\Program Files\qemu>qemu-system-aarch64.exe -nographic -machine musca-a -cpu cortex-m33 -monitor none -serial stdio
-kernel app -m 512 -semihosting
qemu: fatal: Lockup: can't escalate 3 to HardFault (current priority -1)

R00=00000000 R01=00000000 R02=00000000 R03=00000000
R04=00000000 R05=00000000 R06=00000000 R07=00000000
R08=00000000 R09=00000000 R10=00000000 R11=00000000
R12=00000000 R13=ffffffe0 R14=fffffff9 R15=00000000
XPSR=40000003 -Z-- A S handler
FPSCR: 00000000

Если я правильно понимаю, PC=00000000 указывает на проблемы с обработчиком сброса. Я подумал, может быть, эта musca-a доска ожидает, что таблица будет где-то еще, но похоже, что она полностью отсутствует:

psykana@psykana-lap:~$ readelf app -S
There are 26 section headers, starting at offset 0xb1520:

Section Headers:
  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
  [ 0]                   NULL            00000000 000000 000000 00      0   0  0
  [ 1] .init             PROGBITS        00008000 008000 00000c 00  AX  0   0  4
  [ 2] .text             PROGBITS        00008010 008010 01d5b4 00  AX  0   0  8
  [ 3] .fini             PROGBITS        000255c4 0255c4 00000c 00  AX  0   0  4
  [ 4] .rodata           PROGBITS        000255d0 0255d0 003448 00   A  0   0  8
  [ 5] .ARM.exidx        ARM_EXIDX       00028a18 028a18 000008 00  AL  2   0  4
  [ 6] .eh_frame         PROGBITS        00028a20 028a20 000004 00   A  0   0  4
  [ 7] .init_array       INIT_ARRAY      00038a24 028a24 000008 04  WA  0   0  4
  [ 8] .fini_array       FINI_ARRAY      00038a2c 028a2c 000004 04  WA  0   0  4
  [ 9] .data             PROGBITS        00038a30 028a30 000ad8 00  WA  0   0  8
  [10] .persistent       PROGBITS        00039508 029508 000000 00  WA  0   0  1
  [11] .bss              NOBITS          00039508 029508 0001c4 00  WA  0   0  4
  [12] .noinit           NOBITS          000396cc 000000 000000 00  WA  0   0  1
  [13] .comment          PROGBITS        00000000 029508 000049 01  MS  0   0  1
  [14] .debug_aranges    PROGBITS        00000000 029551 000408 00      0   0  1
  [15] .debug_info       PROGBITS        00000000 029959 02e397 00      0   0  1
  [16] .debug_abbrev     PROGBITS        00000000 057cf0 005b3e 00      0   0  1
  [17] .debug_line       PROGBITS        00000000 05d82e 01629f 00      0   0  1
  [18] .debug_frame      PROGBITS        00000000 073ad0 004bf4 00      0   0  4
  [19] .debug_str        PROGBITS        00000000 0786c4 006a87 01  MS  0   0  1
  [20] .debug_loc        PROGBITS        00000000 07f14b 01f27e 00      0   0  1
  [21] .debug_ranges     PROGBITS        00000000 09e3c9 009838 00      0   0  1
  [22] .ARM.attributes   ARM_ATTRIBUTES  00000000 0a7c01 000036 00      0   0  1
  [23] .symtab           SYMTAB          00000000 0a7c38 006ec0 10     24 1282  4
  [24] .strtab           STRTAB          00000000 0aeaf8 002927 00      0   0  1
  [25] .shstrtab         STRTAB          00000000 0b141f 000100 00      0   0  1

Я строю со следующими параметрами (измененный файл набора инструментов из мой предыдущий вопрос):

add_compile_options(
    -mcpu=cortex-m33
    -specs=rdimon.specs
    -O0
    -g
    -mfpu=fpv5-sp-d16
    -mfloat-abi=hard
)
add_link_options(-specs=rdimon.specs -mcpu=cortex-m33 -mfpu=fpv5-sp-d16 -mfloat-abi=hard)

Опять же, это работало нормально для всех процессоров A, которые я пробовал, но не работает для CM33. На самом деле он ломается для любой платы M core и M core QEMU.

Для записи:

 - arm-none-eabi-gcc (GNU Arm Embedded Toolchain 10.3-2021.10)
 - QEMU emulator version 7.0.0 (v7.0.0-11902-g1d935f4a02-dirty)
 - Microsoft Windows [Version 10.0.19044.1645]
 - cmake version 3.22.
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
0
38
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Ваш гостевой код аварийно завершает работу при запуске, что почти всегда происходит из-за проблем с вашей таблицей векторов исключений. Если вы используете опции QEMU -d (например, -d cpu,int,guest_errors,unimp,in_asm), это обычно дает более подробную информацию о том, что именно произошло.

Глядя на ваши заголовки ELF, похоже, что вы не поместили векторную таблицу в свой двоичный файл. Этого требует QEMU (как и реальное оборудование). Обычный способ сделать это — иметь небольшой исходный файл сборки, в котором представлена ​​таблица данных с адресами различных точек входа исключений, хотя есть и другие способы сделать это. (Это один пример.)

Причина, по которой вы не видите этого на процессорах A-профиля, заключается в том, что обработка исключений A-профиля совершенно иная: при сбросе A-профиля выполнение начинается с адреса 0x0, и аналогичным образом исключения принимаются путем установки ПК на фиксированный младший адрес. В M-профиле сброс работает путем чтения начальных значений PC и SP из таблицы векторов, а обработчики исключений начинаются с адресов, также считанных из таблицы векторов. (То есть на А-профиле вещь по магическим младшим адресам — это код, а на М-профиле — это данные, фактически указатели на функции).

Также обратите внимание, что поведение параметра QEMU -kernel отличается для A-профиля и M-профиля: в A-профиле он загружает файл ELF в память и учитывает точку входа ELF (выполнение начнется оттуда). В M-профиле он загрузит файл ELF, но затем перезапустит ЦП аппаратным способом, то есть без установки ПК в точку входа ELF. (Этот вариант в основном по историческим причинам / причинам обратной совместимости.) Если вы хотите «просто загрузить мой файл ELF и установить ПК в его точку входа ELF», вы должны использовать универсальное загрузочное устройство QEMU, которое ведет себя одинаково на всех целях, и не -kernel , что обычно означает «Я ядро ​​Linux, пожалуйста, загрузите меня в любой случайной конкретной цели плюс комбинация поведения «делай то, что я имею в виду», которая кажется лучшей». -kernel, как правило, лучше не использовать, если вы пытаетесь загрузить двоичный файл с «голым железом», а не реальное ядро ​​​​Linux.

Этот аналогичный вопрос о том, как запустить рабочий двоичный файл M-профиля на QEMU также может быть полезен.

Спасибо за ваш подробный ответ. В итоге я использовал Файлы запуска CMSIS. Я также изменил -machine на musca-b1, и мне пришлось переписать код инициализации FPU, чтобы он заработал. Отдельное спасибо за -device loader, использование -kernel действительно было странным.

psykana 15.05.2022 23:46

Другие вопросы по теме