Я пытаюсь сделать ОСРВ, которую мы использовали в школе для работы над моей доской для открытий. В школе мы использовали некоммерческую плату, а ОСРВ загружалась в оперативную память. Мне удалось загрузить это в ОЗУ на плате обнаружения, но у меня проблемы с прерыванием таймера. Я не вижу нигде в RTOS-коде, где процессору сказано перейти к определенному адресу, когда таймер вызывает прерывание. Однако есть адреса и указатели функций, инициализированные этими адресами. Но как процессор знает, как переходить по этим адресам? ОСРВ не использует SCB-> VTOR для перемещения вектора прерывания.
Я удалил весь ненужный (я думаю и надеюсь) код, чтобы показать проблему в меньшем файле. Чтобы еще больше упростить, я мигаю светодиодом на прерывании таймера.
Если я смогу заставить эту небольшую программу работать, то, возможно, я смогу заставить работать RTOS, поэтому любая помощь будет очень признательна. Я сделал несколько комментариев в коде. Итак, чего не хватает в приведенном ниже коде для запуска обработчика прерывания?
#include "stm32f4xx.h"
#include "stm32f4xx_rcc.h"
#include "stm32f4xx_gpio.h"
#include "stm32f4xx_tim.h"
void timer5_init(void);
void led_init();
void init_all(void);
void startup(void) __attribute__((naked)) __attribute__((section (".start_section")) );
#define TIM5_IRQ_VECTOR (0x2001C000+0x108)
#define TIMER5_INTERRUPT void vect_TIM5( void )
TIMER5_INTERRUPT;
void startup(void) {
asm volatile(
" NOP\n"
" LDR SP,=0x2001C000\n" // Set stack
" BL main\n"
".L1: B .L1\n"
);
}
void main() {
init_all();
while (1) {
// Toggle blue led
GPIO_ToggleBits(GPIOD, GPIO_Pin_15); // This works.
ms_delay2(250);
}
}
void init_all() {
led_init();
timer5_init();
}
TIMER5_INTERRUPT {
if (TIM_GetITStatus(TIM5, TIM_IT_Update)) {
// Toggle orange led
GPIO_ToggleBits(GPIOD, GPIO_Pin_13);
TIM_ClearITPendingBit(TIM5, TIM_IT_Update);
}
}
void timer5_init() {
RCC_APB1PeriphClockCmd( RCC_APB1Periph_TIM5, ENABLE);
RCC_APB1PeriphClockLPModeCmd( RCC_APB1Periph_TIM5, ENABLE);
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_DeInit(TIM5);
TIM_TimeBaseStructInit(&TIM_TimeBaseInitStructure);
TIM_TimeBaseInitStructure.TIM_Prescaler = 840-1;
TIM_TimeBaseInit(TIM5, &TIM_TimeBaseInitStructure);
*((void (**)(void) ) TIM5_IRQ_VECTOR ) = vect_TIM5;// Why are they using vect_TIM5 here,
// instead of TIMER5_INTERRUPT?
// Insn't vect_TIM5 just the definition
// of the macro? Why is this working?
NVIC_SetPriority( TIM5_IRQn, 0x00);
NVIC_EnableIRQ( TIM5_IRQn);
TIM_SetCounter(TIM5, 0);
TIM_Cmd( TIM5, ENABLE);
TIM_ITConfig( TIM5, TIM_IT_CC1, ENABLE);
}
void led_init() {
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);
GPIO_InitTypeDef GPIO_InitDef;
GPIO_InitDef.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_15;
GPIO_InitDef.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitDef.GPIO_OType = GPIO_OType_PP;
GPIO_InitDef.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitDef.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOD, &GPIO_InitDef);
}
ЛИНКЕРНЫЙ СЦЕНАРИЙ:
MEMORY
{
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 112K
}
SECTIONS
{
.text :
{
. = ALIGN(4);
*(.start_section)
*(.text)
*(.text.*)
*(.rodata)
*(.rodata*)
*(.glue_7)
*(.glue_7t)
. = ALIGN(4);
} >RAM
.data :
{
. = ALIGN(4);
*(.data)
*(.data.*)
. = ALIGN(4);
} >RAM
.bss :
{
. = ALIGN(4);
_sbss = .;
*(.bss)
*(.bss.*)
*(COMMON)
. = ALIGN(4);
_ebss = . ;
} >RAM
PROVIDE ( end = _ebss );
PROVIDE ( _end = _ebss );
}
«Э, разве вам не обязательно иметь код загрузчика в стартовой сборке, который копирует основной код из флэш-памяти в ОЗУ для выполнения там?» Я забыл упомянуть, что я использую gdb для загрузки программы в оперативную память. Не знаю, почему это работает.
@unwind Нет никакой таблицы векторов. Там почти все не так. Они пытаются делать что-то, что выходит за рамки их знаний. Сначала они должны узнать, как работает микроконтроллер, а затем попытаться сделать сложные системные вещи.
Хорошо, тогда я, должно быть, слишком удалил исходный код. Спасибо.





Разве вам не нужно иметь код загрузчика в стартовой сборке, которая копирует код
mainиз флэш-памяти в ОЗУ, чтобы там можно было выполнить? Если между обработчиком сброса иmain()нет кода, который это делает, то это не будет выполнено. И да, вам нужно будет указать NVIC использовать векторы в ОЗУ.