Qemu: фатальная: Блокировка: не удается увеличить 3 до жесткого (текущий приоритет -1) ошибка -ядро сброшено

#c #linux #embedded #stm32 #qemu

#c #linux #встроенный #stm32 #qemu

Вопрос:

Я пытаюсь эмулировать контроллер STM32F407XX с процессором cortex M4 на QEMU. Я написал файл .ld, как показано ниже:

 ENTRY(_Reset)

MEMORY
{
  FLASH (rx)      : ORIGIN = 0x08000000, LENGTH = 512K
  RAM (xrw)       : ORIGIN = 0x20000000, LENGTH = 128K
  CCMRAM (rw)     : ORIGIN = 0x10000000, LENGTH = 64K
  PERIPHERALS(rw) : ORIGIN = 0x40000000, LENGTH = 128K
}

SECTIONS
{

 .startup . : { stm32.o(.text) } >FLASH
 .text : { *(.text) } 
 .data : { *(.data) } >RAM AT> FLASH
 .bss : { *(.bss COMMON) } >RAM
 . = ALIGN(4);
 . = .   0x400; /* required amount of stack */
 stack_top = 0x20020000;
}
  

Когда я генерирую файл .elf и запускаю код, я получаю ошибку

 Qemu: fatal: Lockup: cant escalate 3 to Hardfault (Current Priority -1) error.
Aborted (Core Dumped)
  

Я чувствую, что это проблема с памятью. Что я делаю не так?
Я выделил флэш-память и оперативную память в соответствии с требованиями справочного руководства для STM32F407.

почему эта ошибка возникает в первую очередь и как я могу устранить эту ошибку? Спасибо.

Комментарии:

1. Жесткий сбой обычно означает ошибку, связанную с указателем или программным счетчиком. Один шаг и видите, куда это попадает? В качестве дополнительного примечания вы должны поместить стек из 0x20000000 -> 0x2000xxxx. Вы не хотите, чтобы оно переполнялось в .bss.

2. Вы можете включить некоторые параметры ведения журнала отладки QEMU с помощью -d (‘in_asm, int, exec, cpu, guest_errors, unimp’, вероятно, являются хорошим набором для начала), который расскажет вам, что делает ваш гостевой код. Я бы начал с проверки того, что в вашем файле ELF есть векторная таблица в том месте, где QEMU ожидает ее найти. В противном случае QEMU немедленно отключит сброс (что и делает аппаратное обеспечение).

3. Ожидается сброс ядра: QEMU переходит в блокировку, но мы неправильно эмулируем блокировку (строго говоря, QEMU должен просто сидеть там, ничего не делая, как это делает реальное оборудование), поэтому мы печатаем дамп регистра и прерываем (). Как я уже говорил в моем предыдущем комментарии, ваша проблема почти наверняка в том, что в вашем двоичном файле нет векторной таблицы.

4. вы правы, теперь я понимаю проблему. Я определил половину таблицы векторов (только для ошибок и системного блока, но не для GPIO и других периферийных устройств, которые ожидает код. Я также определю их в своем файле .s, сгенерирую файл .bin и проверю. Спасибо, Питер.

5. Главное, что у вас должно быть в вашей векторной таблице, — это записи для исходного компьютера и указатель стека. Записи прерывания и исключения стоит ввести, но они понадобятся только при наличии прерывания или исключения. Однако, если вы введете обработчики отладки для других ошибок, вы, по крайней мере, будете знать, когда получите ошибку из-за ошибки в остальной части вашей программы.

Ответ №1:

Размещение векторной таблицы в правильном месте решило проблему. Я следовал всем инструкциям @peter Maydell в комментариях выше. Я добавляю их сюда.

Вы можете включить некоторые параметры ведения журнала отладки QEMU с помощью -d (‘in_asm, int, exec, cpu, guest_errors, unimp’, вероятно, являются хорошим набором для начала), который расскажет вам, что делает ваш гостевой код. Я бы начал с проверки того, что в вашем файле ELF есть векторная таблица в том месте, где QEMU ожидает ее найти. В противном случае QEMU немедленно отключит сброс (что и делает аппаратное обеспечение).

Ожидается сброс ядра: QEMU переходит в блокировку, но мы неправильно эмулируем блокировку (строго говоря, QEMU должен просто сидеть там, ничего не делая, как это делает реальное оборудование), поэтому мы печатаем дамп регистра и прерываем (). Как я уже говорил в моем предыдущем комментарии, ваша проблема почти наверняка в том, что в вашем двоичном файле нет векторной таблицы.

Главное, что у вас должно быть в вашей векторной таблице, — это записи для исходного компьютера и указатель стека. Записи прерывания и исключения стоит ввести, но они понадобятся только при наличии прерывания или исключения. Однако, если вы введете обработчики отладки для других ошибок, вы, по крайней мере, будете знать, когда получите ошибку из-за ошибки в остальной части вашей программы

Ответ №2:

Дополнительная информация для всех, кто, как и я, сталкивается с этим, пытаясь исправить жесткую ошибку qemu: я получил ту же самую ошибку из-за невыполненной инструкции.

Это произошло потому, что я скомпилировал код с -mcpu=cortex-m4 , но запустил qemu с -cpu cortex-m3

Сложность в том, что это работает для большей части кода, потому что gcc чаще всего не использует одну из «инструкций только для m4» (даже в зависимости от уровня оптимизации — это сработало с -O1 , но не сработало с -O2 )…

Ответ №3:

Вам необходимо сбросить ПЗУ после загрузки ядра на ваш компьютер (после armv7m_load_kernel вызова). Вы можете использовать, например:

 rom_check_and_register_reset();
qemu_devices_reset();
  

Процессор должен запуститься при сбросе обработчика.

Комментарии:

1. Проблема заключалась в том, что обработчик сброса был размещен не там, где ожидал процессор. Работал без сброса ПЗУ.