Я пытаюсь создать ОСРВ, которую мы использовали в школе, чтобы работать на моей доске открытий.В школе мы использовали некоммерческую плату, а ОСРВ была загружена в ОЗУ.Мне удалось загрузить его в оперативную память на плате обнаружения, но у меня проблемы с прерыванием по таймеру.Я не вижу нигде в RTOS-коде, где процессору приказано перейти на определенный адрес, когда таймер вызывает прерывание.Однако существуют адреса и указатели функций, инициализированные этими адресами.Но как процессор знает, как перейти на эти адреса?ОСРВ не использует SCB-> VTOR для перемещения вектора прерывания.
Я удалил весь ненужный (я думаю и надеюсь) код, чтобы показать проблему в меньшем файле.Чтобы упростить еще больше, я мигаю светодиодом на прерывании таймера.
Если я смогу заставить работать эту небольшую программу, то, возможно, я смогу заставить работать ОСРВ, поэтому любая помощь будет высоко цениться.Я сделал несколько комментариев в коде.Итак, чего не хватает в приведенном ниже коде для запуска обработчика прерываний?
#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);
}
СКРИПТ LINKER:
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 );
}