stm32-rs / bxcan

bxCAN peripheral driver for STM32 chips

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

can initialization process doesn't work on stm32f4

xoviat opened this issue · comments

This does seem to work (though I haven't yet sent a message):

    dp.RCC.apb2enr.write(|w| w.syscfgen().enabled());

    let gpioa = dp.GPIOA.split();
    let gpiob = dp.GPIOB.split();
    let gpioc = dp.GPIOC.split();
    let mut rcc = dp.RCC.constrain();

    let clocks = rcc
        .cfgr
        .use_hse(16.mhz())
        .sysclk(48.mhz())
        .pclk1(24.mhz())
        .freeze();

    let mut delay = Delay::new(cp.SYST, clocks);

    CAN1::enable(&mut rcc.apb1);

    dp.CAN1.mcr.modify(|_, w| w.sleep().clear_bit());
    let mut waiting = true;
    while waiting {
        let msr = dp.CAN1.msr.read();
        if msr.slak().bit_is_set() {
            waiting = false;
        }
    }

    dp.CAN1.mcr.modify(|_, w| w.dbf().clear_bit());

    let r_mcr = dp.CAN1.mcr.read().bits();
    let r_msr = dp.CAN1.msr.read().bits();
    let r_tsr = dp.CAN1.tsr.read().bits();

    /* request initializiation */
    dp.CAN1.mcr.modify(|_, w| w.inrq().set_bit());
    let mut waiting = true;
    while waiting {
        let msr = dp.CAN1.msr.read();
        if msr.inak().bit_is_set() {
            waiting = false;
        }
    }

    dp.CAN1.btr.modify(|_, w| unsafe { w.bits(0x001c_0003) });

compare to the initialization process in this pacakge

        can.mcr
            .modify(|_, w| w.sleep().clear_bit().inrq().set_bit());
        while can.msr.read().inak().bit_is_clear() {}

        can.mcr
            .modify(|_, w| w.sleep().set_bit().inrq().clear_bit());
        while can.msr.read().slak().bit_is_clear() {}

        let msr = can.msr.read();
        while !msr.slak().bit_is_set() {
            can.mcr
                .modify(|_, w| w.abom().set_bit().sleep().clear_bit());
        }

I'm not sure why it's currently done this way, but the slak() bit is not set.

Relevant parts from the Reference Manual:

If software requests entry to initialization mode by setting the INRQ bit while bxCAN is in Sleep mode, it must also clear the SLEEP bit

bxcan code is doing excactly that

After the SLEEP bit has been cleared, Sleep mode is exited once bxCAN has synchronized with the CAN bus, refer to Figure 336. The Sleep mode is exited once the SLAK bit has been cleared by hardware.

We are not waiting for SLAK to be clear, which appears to be the root cause.

As why this works on stm32f1xx and not on stm32f4xx I can only guess: stm32f1xx probably was running at a slow enough clock for the flag to be cleared in time

note: this may still be needed, but I misunderstood the issue. keep this open for a bit.