Прерывание SysTick заставляет выполнение перейти к 0x1fffxxxx на STM32F030 - PullRequest
0 голосов
/ 03 июля 2018

Я пытаюсь использовать SysTick_Handler в SW4STM32 для Linux, но всякий раз, когда срабатывает прерывание SysTick, выполнение переходит куда-то в системную память. Насколько я понимаю, он должен перейти в void SysTick_Handler(void), который я объявил, или в противном случае, в Default_Handler, объявленный в startup_stm32.s, где определена таблица векторов прерываний. Я установил точку останова в своем SysTick_Handler, но она никогда не достигается. В приведенном ниже коде он проходит через init_systick() и остается в бесконечном цикле for, если я не включаю SysTick_CTRL_TICKINT_Msk, как ожидалось, но когда я его включаю, отладчик говорит мне, что он заканчивается где-то около адреса 0x1fffda7c.

main.c:

#include "stm32f0xx.h"

volatile uint32_t ticks = 0;

void SysTick_Handler(void) {
    ticks++;
}

void init_systick(void) {
    SysTick->LOAD = 43999;
    SCB->SHP[1] |= 0x40000000L;
    SysTick->VAL = 0;
    SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk;
}

int main(void)
{
    init_systick();
    for(;;);
}

Я подтвердил из файла .map, что компоновщик использует объявленный SysTick_Handler вместо Default_Handler.

Я также попробовал следующий вариант, чтобы использовать стандартную периферийную библиотеку для настройки, наряду с другими значениями приоритета прерывания, с такими же результатами:

#include "stm32f0xx.h"

volatile uint32_t ticks = 0;

void SysTick_Handler(void) {
    ticks++;
}

void init_systick(void) {
    SysTick_Config(44000);
    NVIC_EnableIRQ(SysTick_IRQn);
    NVIC_SetPriority(SysTick_IRQn, 0);
}

int main(void)
{
    init_systick();
    for(;;);
}

Это не должно относиться к делу, но поскольку у цели нет временного кристалла, я также изменил void SetSysClock(void) в system_stm32f0xx.c, чтобы использовать часы HSI и PLL, которые, кажется, работают правильно:

static void SetSysClock(void)
{
    RCC->CFGR = (RCC->CFGR & ~RCC_CFGR_SW) | RCC_CFGR_SW_HSI;
    while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_HSI) ;
    FLASH->ACR = FLASH_ACR_PRFTBE | FLASH_ACR_LATENCY;
    RCC->CR &= ~RCC_CR_PLLON;
    while (RCC->CR & RCC_CR_PLLRDY) ;
    RCC->CFGR = (RCC->CFGR & ~RCC_CFGR_PLLMUL & ~RCC_CFGR_PLLSRC) | RCC_CFGR_PLLMUL11;   // PLL takes 8 MHz HSI / 2 as input
    RCC->CR |= RCC_CR_PLLON;
    while (!(RCC->CR & RCC_CR_PLLRDY)) ;
    RCC->CFGR = (RCC->CFGR & ~RCC_CFGR_SW) | RCC_CFGR_SW_PLL;
    while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL) ;
}

- РЕДАКТИРОВАТЬ: Дополнительная информация запрашивается в комментариях -

Это ядро ​​M0, поэтому оно не имеет перемещения векторной таблицы. Из справочного руководства, раздел 2.5 (стр. 44):

В отличие от Cortex ® M3 и M4, процессор M0 не поддерживает перемещение векторной таблицы.

Адрес 0x00000000 должен быть сопоставлен либо с флэш-памятью по адресу 0x08000000, системной памятью по адресу 0x1fffd800, либо с SRAM по адресу 0x20000000. Память по адресу 0x00000000 совпадает с системной памятью по адресу 0x1fffd800, хотя SYSCFG_CFGR1 MEM_MODE установлен в 00, что должно отображать флэш-память там. Основная флэш-память по адресу 0x08000000 содержит правильную таблицу векторов, но адрес 0x00000000 заполняется адресом 0x1fffd99d для вектора SysTick (и всех других ненулевых векторов, кроме вектора сброса, который равен 0x1fffdc41); векторы, показанные отладчиком по адресу 0x00000000, соответствуют наблюдаемому поведению. Вся эта информация была собрана во время паузы в точке останова по адресу 0x08000298 (правильная позиция во флэш-памяти, куда был загружен правильный код) перед выполнением прерывания.

Ответы [ 3 ]

0 голосов
/ 30 января 2019

VTOR указан в справочном руководстве arm-v6. Это хорошая идея, чтобы проверить это. https://static.docs.arm.com/ddi0419/d/DDI0419D_armv6m_arm.pdf

0xE000ED08 VTOR RW 0x00000000a Регистр смещения векторной таблицы, VTOR на стр. B3-231

Это справочное руководство предназначено для архитектуры arm-v6M, которая является архитектурой для процессоров cortex-m0. Это Библия. Большинство общих функций cortex-m0 линии stm не будут упоминаться в руководствах по stm refrenece, только в кронштейне руки.

Я повторюсь, проверь VTOR.

И убедитесь, что вы строите правильную линию STM32F030!

Микросхемы STM32F030x4 и STM32F030x6 имеют карту памяти, отличную от STM32F030x8.

0 голосов
/ 02 февраля 2019

Похоже, что проблема с файлом компоновщика.

Можете ли вы убедиться, что в вашем файле компоновщика есть что-то похожее на следующее? (если это файл по умолчанию, он, вероятно, будет намного сложнее).

. = 0;
.text 0 :
{
    *(.vector);
    crt0*(.text*);
main*(.text*);
    *(.text*);
} > flash

По сути, это говорит о том, что «текст» (код) программы начинается с адреса 0x0, и первое, что нужно добавить, - это таблица векторов, за которой следует код запуска, main, а затем другой код.

Затем вы также захотите проверить, есть ли у вас файл, определяющий содержимое этой векторной таблицы, который также соглашается, что он должен быть по адресу 0x0. Этот пример взят из ATSAMD21E18A.

.section .vector, "a", %progbits

.equ stack_base, 0x20004000

.word stack_base
.word reset_handler
.word nmi_handler
.word hardfault_handler
.word 0
// ...
.word 0
.word systick_handler
// ...

Важно то, что он помечен как раздел vector, который файл компоновщика будет пытаться поместить в 0x0. Для процессора с VTOR (например, M0 +) эта таблица может быть указана в C без каких-либо специальных разметок, и его местоположение не будет иметь значения, но поскольку у вас нет VTOR, вам нужно убедиться, что компоновщик знает, как поставить этот раздел прямо в 0x0.

0 голосов
/ 03 июля 2018

Согласно данным , эта область является системной памятью (для встроенного загрузчика). Вы можете попробовать две вещи:

  1. Дважды проверьте контакты BOOTx, чтобы убедиться, что MCU загружает FLASH вместо системной памяти.
  2. Убедитесь, что вы присвоили SCB->VTOR правильному адресу вашей таблицы векторов прерываний.
...