Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DWT clock cycle count stuck unless trace is enabled #252

Closed
bschwind opened this issue Jul 29, 2020 · 3 comments · Fixed by #254
Closed

DWT clock cycle count stuck unless trace is enabled #252

bschwind opened this issue Jul 29, 2020 · 3 comments · Fixed by #254
Labels
bug Something isn't working

Comments

@bschwind
Copy link
Contributor

I tried using a MonoTimer to measure time between two events (in my case, some button pushes). I noticed the time-based code was never firing, and dug into the code until I discovered that DWT::get_cycle_count always returns 1073741824 (2^30)

In order for clock cycles to be successfully reported from DWT, I have to call cp.DCB.enable_trace();

Here is a minimal reproduction of the issue, printing the clock cycle counts over a serial interface. My hardware is a "black pill" stm32f103c8t6, specifically this dev board. I flash and monitor output via a CP2102 serial-usb adapter. I'm not currently using a debugger probe of any sort.

#![deny(unsafe_code)]
#![no_main]
#![no_std]

use panic_halt as _;

use cortex_m_rt::entry;
use stm32f1xx_hal::{
    pac,
    prelude::*,
    serial::{Config, Serial},
};

use core::fmt::Write;

#[entry]
fn main() -> ! {
    let mut cp = cortex_m::peripheral::Peripherals::take().unwrap();
    let p = pac::Peripherals::take().unwrap();

    let mut flash = p.FLASH.constrain();
    let mut rcc = p.RCC.constrain();
    let clocks = rcc.cfgr.freeze(&mut flash.acr);

    let mut afio = p.AFIO.constrain(&mut rcc.apb2);
    let mut gpioa = p.GPIOA.split(&mut rcc.apb2);

    let tx = gpioa.pa9.into_alternate_push_pull(&mut gpioa.crh);
    let rx = gpioa.pa10;

    let serial = Serial::usart1(
        p.USART1,
        (tx, rx),
        &mut afio.mapr,
        Config::default().baudrate(115200.bps()),
        clocks,
        &mut rcc.apb2,
    );

    let (mut tx, _rx) = serial.split();

    // Needed in order for MonoTimer to work properly
    cp.DCB.enable_trace();

    let mut delay = stm32f1xx_hal::delay::Delay::new(cp.SYST, clocks);
    let mono_timer = stm32f1xx_hal::time::MonoTimer::new(cp.DWT, clocks);

    let start = mono_timer.now();

    loop {
        let elapsed = start.elapsed();
        writeln!(tx, "Elapsed clock cycles {}\r", elapsed).unwrap();
        delay.delay_ms(100_u32);
    }
}

I found a few older issues in earlier repositories about this:

@TheZoq2 TheZoq2 added the bug Something isn't working label Aug 1, 2020
@TheZoq2
Copy link
Member

TheZoq2 commented Aug 1, 2020

Huh, I didn't know you could enable the DWT without a debugger attached, we probably should do that then... Though it still feels a bit odd to use the debug peripheral for timekeeping

@fuchsnj
Copy link

fuchsnj commented Aug 7, 2020

I just tested this on a bluepill, and without cp.DCB.enable_trace(), DWT::get_cycle_count() always returns 1073741824 (same as @bschwind ). However, when I enable trace, it always returns 0.
I haven't been able to get it to actually count cycles yet.

@fuchsnj
Copy link

fuchsnj commented Aug 7, 2020

Ah, spoke too soon. If I enable trace before I create the MonoTimer everything is working fine on my bluepill. Enabling it after makes it always return 0.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants