首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在引导加载程序运行时,stm32l433上的应用程序在第一次中断表单定时器后停止

在引导加载程序运行时,stm32l433上的应用程序在第一次中断表单定时器后停止
EN

Stack Overflow用户
提问于 2022-06-23 09:50:42
回答 2查看 61关注 0票数 0

我需要一些帮助,我的锈蚀应用程序运行在一个核-64评估板与一个stm32L433单片机。在应用程序启动之前,引导加载程序检查应用程序是否存在并启动它。在应用程序中,我定义了一个具有中断的计时器,它每秒钟增加一个计数器。当第一次触发中断时,应用程序将停止。

如果我在MCU上没有引导加载程序就运行应用程序,那么一切都按预期的方式工作。

有人能解释一下为什么应用程序会停止吗?或者给我一个提示,如何使应用程序与启用的计时器中断一起运行?

引导加载器内存x

代码语言:javascript
复制
MEMORY
{
  /* NOTE K = KiBi = 1024 bytes */
  FLASH : ORIGIN = 0x8000000, LENGTH = 64K
  RAM : ORIGIN = 0x20000000, LENGTH = 8K
}

引导程序main.rs

代码语言:javascript
复制
#![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

代码语言:javascript
复制
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

代码语言:javascript
复制
#![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上找到。

EN

回答 2

Stack Overflow用户

发布于 2022-06-23 12:50:23

@巴斯比是对的。中断向量表的位置需要更新。在引导加载程序中执行cortex_m::asm::bootload(vt);之前,需要用cortex_m::Peripherals::take().unwrap().SCB.vtor.write(FLASH_USER + 4);更新中断向量表的位置,并且中断在应用程序中工作。

谢谢你的暗示。

票数 1
EN

Stack Overflow用户

发布于 2022-06-24 01:53:46

引导加载程序和应用程序有不同的中断向量表。在应用程序中,如果不配置将中断向量表更改为应用程序向量表,它将跳回引导加载程序代码并可能导致挂起。为了处理这个问题,它依赖于微控制器,我们可能有以下几种方法:

如果能够更改ISR表,只需跳转到application.

  • If之后更改它,事情就更复杂了,因为您需要在引导加载程序中有一些特殊的句柄来调用应用程序中的处理程序.
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72728129

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档