Hi there!
Strangely, my stm32f103xx board (blue pill) is not able to handle exceptions any more. Maybe half a year back I developed firmware for it in rust, which was using exceptions (e.g. for the SysTick). I don`t have access to the source code any more.
Now I am struggling at creating a simple Systick based ms counter. It does not really matter what I do, as soon as the exception fires, the processor stops. It seems like it is never returning from the exception handler, and resuming the main program.
What I have in mind is, that one of the cortex-m, cortex-m-rt, or stm32f1xx crates got updated, and broke something. It is also possible, that the rust compiler has a new bug...
For debugging the issue, I disassembled the produced flash image, everything including interrupt and exception tables looks good.
Sadly I can`t debug it until next week, I do not have a suiting ST-Link / SWD debugger, because I destroyed my last one (trying to flash it with custom rust bootloader -_-).
Example:
#![no_std]
#![no_main]
use core::panic::PanicInfo;
use cortex_m::asm;
use cortex_m_rt::{entry, exception, ExceptionFrame};
use embedded_hal_usb::UsbDevice;
use stm32f1::stm32f103::{CorePeripherals, Peripherals, RCC, SYST};
// Not really correct, but does not matter now
const CORE_SPEED: u32 = 72_000_000;
#[entry]
fn main() -> ! {
let peripherals = Peripherals::take().unwrap();
let core_peripherals = CorePeripherals::take().unwrap();
let gpioa = peripherals.GPIOA;
let gpioc = peripherals.GPIOC;
let rcc = peripherals.RCC;
let mut syst = core_peripherals.SYST;
let usb = peripherals.USB;
let nciv = core_peripherals.NVIC;
// Enable gpio peripheral block clocks
rcc.apb2enr
.modify(|_, w| w.iopaen().enabled().iopcen().enabled());
// Setup LED
gpioc
.crh
.modify(|_, w| w.mode13().output2().cnf13().push_pull());
gpioc.odr.modify(|_, w| w.odr13().bit(false));
// setup_clocks(&rcc);
// let mut usb_device = UsbDevice::<stm32f103xx_usb_hal::UsbDriver>::new(&rcc.apb1enr, usb);
// usb_device.initialize();
// Wait for a couple of CPU cycles. apb2enr and gpioa take time to adjust.
sleep_some();
setup_systick(&mut syst);
loop {
gpioc.odr.modify(|r, w| w.odr13().bit(!r.odr13().bit()));
for _ in 0..50000 {
sleep_some();
}
}
}
/// Sets sysclk to 72 MHZ
/// USB clock to 48 MHZ
/// Uses HSE with PLL as Sysclock
/// Disables HSI
/// APB1 clock to 36 MHZ, because max
/// Enables all required peripheral clocks (USB, USART, ...)
fn setup_clocks(rcc: &RCC) {
// Enable PLL and HSE
rcc.cr.modify(|_, w| w.hseon().on().pllon().on());
// Wait until PLL and HSE are ready
while !rcc.cr.read().hserdy().bit_is_set() && !rcc.cr.read().pllrdy().bit_is_set() {}
// Select PLL as sysclock source, set HSE as PLL source, multiply PLL by 9,
// divide PLL by 1.5 for usb clock, divide APB1 clock by 2 for 36 MHZ
rcc.cfgr.modify(|_, w| {
w.sw()
.pll()
.pllsrc()
.hse_div_prediv()
.pllmul()
.mul9()
.usbpre()
.div1_5()
.ppre1()
.div2()
});
// We do not require HSI any more
rcc.cr.modify(|_, w| w.hsion().clear_bit());
}
fn setup_systick(syst: &mut SYST) {
syst.set_clock_source(cortex_m::peripheral::syst::SystClkSource::Core);
// Please ignore the CORE_SPEED counter value. I was to lazy coming up with a large number O.o
syst.set_reload(CORE_SPEED);
syst.clear_current();
syst.enable_counter();
syst.enable_interrupt();
}
#[exception]
fn SysTick() {
static mut TEST: usize = 0;
*TEST += 1;
}
// #[exception]
// fn DefaultHandler(_irq: i16) {
// return;
// }
#[exception]
fn HardFault(_frame: &ExceptionFrame) -> ! {
loop {}
}
fn sleep_some() {
for _ in 0..5 {
asm::nop();
}
}
#[panic_handler]
fn panic_impl(_info: &PanicInfo) -> ! {
asm::bkpt();
loop {
asm::nop();
}
}