我需要一些帮助,我的锈蚀应用程序运行在一个核-64评估板与一个stm32L433单片机。在应用程序启动之前,引导加载程序检查应用程序是否存在并启动它。在应用程序中,我定义了一个具有中断的计时器,它每秒钟增加一个计数器。当第一次触发中断时,应用程序将停止。
如果我在MCU上没有引导加载程序就运行应用程序,那么一切都按预期的方式工作。
有人能解释一下为什么应用程序会停止吗?或者给我一个提示,如何使应用程序与启用的计时器中断一起运行?
引导加载器内存x
MEMORY
{
/* NOTE K = KiBi = 1024 bytes */
FLASH : ORIGIN = 0x8000000, LENGTH = 64K
RAM : ORIGIN = 0x20000000, LENGTH = 8K
}引导程序main.rs
#![no_main]
#![no_std]
extern crate cortex_m;
#[macro_use]
extern crate cortex_m_rt as rt;
extern crate panic_semihosting;
extern crate stm32l4xx_hal;
use rt::{entry, ExceptionFrame};
const FLASH_USER: u32 = 0x0801_0000;
#[entry]
fn main() -> ! {
//check if application is present
let sp = unsafe { (FLASH_USER as *const u32).read() };
if sp & 0xfffe_0000 == 0x2000_0000 {
let vt = FLASH_USER as *const u32;
unsafe {
cortex_m::asm::bootload(vt);
}
}
panic!("No application found")
}
#[exception]
unsafe fn HardFault(ef: &ExceptionFrame) -> ! {
panic!("{:#?}", ef);
}应用内存x
MEMORY
{
/* NOTE K = KiBi = 1024 bytes */
/* Application without bootloader */
/* FLASH : ORIGIN = 0x8000000, LENGTH = 256K */
/* Application with bootloader */
FLASH : ORIGIN = 0x8010000, LENGTH = 192K
RAM : ORIGIN = 0x20000000, LENGTH = 64K
}应用main.rs
#![no_main]
#![no_std]
extern crate cortex_m;
#[macro_use]
extern crate cortex_m_rt as rt;
extern crate cortex_m_semihosting;
extern crate panic_semihosting;
extern crate stm32l4xx_hal as hal;
use core::{
cell::RefCell,
fmt::Write,
ops::DerefMut,
sync::atomic::{AtomicU32, Ordering},
};
use cortex_m::{
interrupt::{free, Mutex},
peripheral::NVIC,
};
use cortex_m_semihosting::hio::hstdout;
use hal::{
delay::Delay,
interrupt,
prelude::*,
timer::{Event, Timer},
};
use rt::{entry, ExceptionFrame};
static COUNT: AtomicU32 = AtomicU32::new(0);
static TIMER_TIM7: Mutex<RefCell<Option<Timer<hal::stm32::TIM7>>>> = Mutex::new(RefCell::new(None));
#[entry]
fn main() -> ! {
let mut hstdout = hstdout().unwrap();
writeln!(hstdout, "Hello from main").unwrap();
let cortex_peripherals = cortex_m::Peripherals::take().unwrap();
let hal_peripherals = hal::stm32::Peripherals::take().expect("failed to get stm32 peripherals");
let mut flash = hal_peripherals.FLASH.constrain();
let mut rcc = hal_peripherals.RCC.constrain();
let mut pwr = hal_peripherals.PWR.constrain(&mut rcc.apb1r1);
let clocks = rcc.cfgr.freeze(&mut flash.acr, &mut pwr);
let mut delay = Delay::new(cortex_peripherals.SYST, clocks);
unsafe { NVIC::unmask(hal::stm32::Interrupt::TIM7) };
let mut timer = Timer::tim7(hal_peripherals.TIM7, 1.Hz(), clocks, &mut rcc.apb1r1);
timer.listen(Event::TimeOut);
free(|cs| {
TIMER_TIM7.borrow(cs).replace(Some(timer));
});
writeln!(hstdout, "Timer init done!").unwrap();
let mut last_count = COUNT.load(Ordering::Relaxed);
loop {
writeln!(hstdout, "loop").unwrap();
delay.delay_ms(100_u32);
let count = COUNT.load(Ordering::Relaxed);
if last_count != count {
last_count = count;
writeln!(hstdout, "count changed").unwrap();
}
}
}
#[interrupt]
fn TIM7() {
let mut hstdout = hstdout().unwrap();
writeln!(hstdout, "Hello, from TIMER").unwrap();
free(|cs| {
if let Some(ref mut tim7) = TIMER_TIM7.borrow(cs).borrow_mut().deref_mut() {
tim7.clear_interrupt(Event::TimeOut);
}
});
COUNT.fetch_add(1, Ordering::Relaxed);
}
#[exception]
unsafe fn HardFault(ef: &ExceptionFrame) -> ! {
panic!("{:#?}", ef);
}我使用的代码也可以在https://github.com/robhany/stm32l4-bootloader-test上找到。
发布于 2022-06-23 12:50:23
@巴斯比是对的。中断向量表的位置需要更新。在引导加载程序中执行cortex_m::asm::bootload(vt);之前,需要用cortex_m::Peripherals::take().unwrap().SCB.vtor.write(FLASH_USER + 4);更新中断向量表的位置,并且中断在应用程序中工作。
谢谢你的暗示。
发布于 2022-06-24 01:53:46
引导加载程序和应用程序有不同的中断向量表。在应用程序中,如果不配置将中断向量表更改为应用程序向量表,它将跳回引导加载程序代码并可能导致挂起。为了处理这个问题,它依赖于微控制器,我们可能有以下几种方法:
如果能够更改ISR表,只需跳转到application.
https://stackoverflow.com/questions/72728129
复制相似问题