Closed andreyk0 closed 5 years ago
let clocks = rcc.cfgr.use_hse(time::Hertz(72_000_000)).freeze(&mut flash.acr);
or shorter
let clocks = rcc.cfgr.use_hse(72.mhz()).freeze(&mut flash.acr);
Thanks but how does one actually control prescalers then? I have a pretty basic "blue pill" board with 8Mhz HSE clock. It looked to me as if the library let you specify HSE clock and the desired other frequencies and then it tries to compute/set prescalers. Do you happen to have an example with non-default prescaler config?
Hi @andreyk0
You may specify HSE frequency and other derived clocks including sysclk, pclk1, pclk2, adcclk. For instance, I have been testing ADC clocks for #67 using the following clock configurations:
let clocks = rcc.cfgr.use_hse(8.mhz()).sysclk(8.mhz()).pclk1(2.mhz()).adcclk(1.mhz()).freeze(&mut flash.acr);
let clocks = rcc.cfgr.use_hse(8.mhz()).sysclk(16.mhz()).pclk1(4.mhz()).adcclk(2.mhz()).freeze(&mut flash.acr);
let clocks = rcc.cfgr.use_hse(8.mhz()).sysclk(24.mhz()).pclk1(9.mhz()).adcclk(3.mhz()).freeze(&mut flash.acr);
let clocks = rcc.cfgr.use_hse(8.mhz()).sysclk(24.mhz()).pclk1(12.mhz()).adcclk(4.mhz()).freeze(&mut flash.acr);
let clocks = rcc.cfgr.use_hse(8.mhz()).sysclk(24.mhz()).pclk1(12.mhz()).adcclk(6.mhz()).freeze(&mut flash.acr);
let clocks = rcc.cfgr.use_hse(8.mhz()).sysclk(36.mhz()).pclk1(12.mhz()).adcclk(6.mhz()).freeze(&mut flash.acr);
let clocks = rcc.cfgr.use_hse(8.mhz()).sysclk(32.mhz()).pclk1(16.mhz()).adcclk(8.mhz()).freeze(&mut flash.acr);
let clocks = rcc.cfgr.use_hse(8.mhz()).sysclk(40.mhz()).pclk1(20.mhz()).adcclk(10.mhz()).freeze(&mut flash.acr);
let clocks = rcc.cfgr.use_hse(8.mhz()).sysclk(48.mhz()).pclk1(24.mhz()).adcclk(12.mhz()).freeze(&mut flash.acr);
Library will attempt to calculate prescalers and write their values into MCU registers. If provided values are not consistent, then one of the asserts in src/rcc.rs will be triggered. So you better use some kind of debug output (semihosting or itm) when adjusting clocks for your system.
Regards, Sergey
Hi @burrbull , You are probably talking about HSI which is internal 8MHz oscillator. HSE is external crystal oscillator: according to your picture it can be between 4 and 12 MHz. Blue Pill has external 8 MHz crystal on board.
IIRC by default HAL configures HSI as a clock source. But it can be changed using use_hse() call, specifying actual crystal frequency as a parameter.
Regards, Sergey
@geomatsi nice, thanks for the example!
As was discussed in #67, more documentation for this would be nice. I'll try and look into adding that next week
Got some time to play more (sorry, I'm new to this), so far only one configuration works for me:
let clocks = rcc .cfgr .use_hse(8.mhz()) .sysclk(8.mhz()) .pclk1(2.mhz()) .adcclk(1.mhz()) .freeze(&mut flash.acr);
All of the other ones result in a hang. E.g. this hangs: https://github.com/andreyk0/stm32_blink/blob/master/src/main.rs#L35
% make debug
cargo build
warning: unused manifest key: profile.development
Finished dev [unoptimized + debuginfo] target(s) in 0.10s
gdb-multiarch -x openocd.gdb -q target/thumbv7m-none-eabi/debug/stm32_blink
Reading symbols from target/thumbv7m-none-eabi/debug/stm32_blink...
0xfffffffe in ?? ()
Breakpoint 1 at 0x8003000: file /home/andrey/.cargo/registry/src/github.com-1ecc6299db9ec823/cortex-m-rt-0.6.8/src/lib.rs, line 540.
Breakpoint 2 at 0x800321a: file /home/andrey/.cargo/registry/src/github.com-1ecc6299db9ec823/cortex-m-rt-0.6.8/src/lib.rs, line 530.
Breakpoint 3 at 0x8002e78: file /home/andrey/.cargo/registry/src/github.com-1ecc6299db9ec823/panic-halt-0.2.0/src/lib.rs, line 33.
semihosting is enabled
Loading section .vector_table, size 0x130 lma 0x8000000
Loading section .text, size 0x30fa lma 0x8000130
Loading section .rodata, size 0xbac lma 0x8003230
Start address 0x8002fba, load size 15830
Transfer rate: 16 KB/sec, 5276 bytes/write.
Note: automatically using hardware breakpoints for read-only addresses.
DefaultPreInit () at /home/andrey/.cargo/registry/src/github.com-1ecc6299db9ec823/cortex-m-rt-0.6.8/src/lib.rs:546
546 pub unsafe extern "C" fn DefaultPreInit() {}
(gdb) cont
Continuing.
^C
Program received signal SIGINT, Interrupt.
0xfffffffe in ?? ()
(gdb) bt
#0 0xfffffffe in ?? ()
#1 <signal handler called>
#2 stm32f1::stm32f103::rcc::cfgr::<impl stm32f1::stm32f103::rcc::CFGR>::modify (self=0x40021004, f=...)
at /home/andrey/.cargo/registry/src/github.com-1ecc6299db9ec823/stm32f1-0.7.1/src/stm32f103/rcc/cfgr/mod.rs:20
#3 0x0800228e in stm32f1xx_hal::rcc::CFGR::freeze (self=..., acr=0x20004e74) at /home/andrey/work/3rdparty/embedded/Rust/stm32-rs-stm32f1xx-hal/src/rcc.rs:310
#4 0x080005ba in main () at src/main.rs:35
(gdb)
Longer session: https://github.com/andreyk0/stm32_blink/blob/master/eg.gdb.session
CPU is STM32F103C8T6
, 8Mhz HW clock.
I must be missing some config detail here but so far haven't noticed which yet.
My local stm32-rs-stm32f1xx-hal
is at 5ad17fc7097618400c2b0afc23215e25e7372410
at the moment.
Thanks for looking at this!
Hmm.. The same minimal example works fine on my BluePill board:
#[entry]
fn main() -> ! {
let dp = hal::stm32::Peripherals::take().unwrap();
let mut rcc = dp.RCC.constrain();
let mut flash = dp.FLASH.constrain();
let clocks = rcc.cfgr.use_hse(8.mhz()).sysclk(16.mhz()).pclk1(4.mhz()).adcclk(2.mhz()).freeze(&mut flash.acr);
//let clocks = rcc.cfgr.use_hse(8.mhz()).sysclk(36.mhz()).pclk1(12.mhz()).adcclk(6.mhz()).freeze(&mut flash.acr);
//let clocks = rcc.cfgr.use_hse(8.mhz()).sysclk(56.mhz()).pclk1(28.mhz()).adcclk(14.mhz()).freeze(&mut flash.acr);
let mut gpioc = dp.GPIOC.split(&mut rcc.apb2);
let mut led = gpioc.pc13.into_push_pull_output(&mut gpioc.crh);
loop {
hprintln!("Hello World!").unwrap();
led.set_high();
delay(5000);
led.set_low();
delay(500);
}
}
fn delay(count: u32) {
for _ in 0..count {
cm::asm::nop();
}
}
I used the same versions of dependencies as in your case. So I have no idea what could go wrong in your case. Could you please show the dump of registers after you system stucks ? You may use openocd telnet console to halt system and dump registers.
The only difference that I noticed so far is the content of memory file. Here is the content of my memory.x:
$ cat memory.x
MEMORY
{
FLASH : ORIGIN = 0x08000000, LENGTH = 64K
RAM : ORIGIN = 0x20000000, LENGTH = 20K
}
_stack_start = ORIGIN(RAM) + LENGTH(RAM);
_stext = ORIGIN(FLASH) + 0x400;
_heap_size = 1024;
Thanks! I took your memory settings (just in case) but no luck, updated https://github.com/andreyk0/stm32_blink/blob/master/eg.gdb.session with a new debug session (single steps before hang). Everything seems fine until it touches SW register and then PC becomes corrupt right after that and it jumps off the rails. Sorry to waste your time with this, must be something really dumb that I'm doing but I don't see it. Feel free to ignore me, I'll keep poking when I have free time, it's as good of a starting point as any for me to try to figure out this system. Thanks again for your help!
Just in case, which rust toolchain are you using ?
I think these are the main parts, anything else that matters?
% cargo --version
cargo 1.35.0 (6f3e9c367 2019-04-04)
% rustc --version
rustc 1.35.0 (3c235d560 2019-05-20)
% dpkg -l | grep arm-none-eabi
ii binutils-arm-none-eabi 2.32-1ubuntu4+11 amd64 GNU assembler, linker and binary utilities for ARM Cortex-R/M processors
ii gcc-arm-none-eabi 15:7-2018-q2-6 amd64 GCC cross compiler for ARM Cortex-R/M processors
ii libnewlib-arm-none-eabi 3.1.0.20181231-1 all C library and math library compiled for bare metal using Cortex A/R/M
ii libstdc++-arm-none-eabi-newlib 15:7-2018-q2-5+12 all GNU Standard C++ Library v3 for ARM Cortex-R/M processors (newlib)
%
Hmm, maybe there's something wrong with the toolchain or the hardware, tried git clean -fdx
everywhere and they sysclk(16.mhz())
blinked but then tried one more config and it hung. Did a quick memory dump and compared registers with the docs - seem allright.
Sorry, please ignore this for now, this is most likely something weird in my environment. I'll go step-by-step and check everything again when I have a bit more time.
The other possibility that comes to mind is a fake/non STM32 chip.
Had some time to play with it again this weekend, the only diff is I ran rustup update
everything seems to work now. Still not sure what it was but thanks for the help.
Compared to RTOS as well, the only tiny diff I've noticed is the treatment of "don't care" 0xxx
bits. RTOS seems to zero them all out while Rust code only zeroes out the significant bit. According to the docs it shouldn't matter thought.
Rust HPRE: 0111 0xxx: SYSCLK not divided
RTOS HPRE: 0000 0xxx: SYSCLK not divided
Rust PPRE2: 011 0xx HCLK not divided
RTOS PPRE2: 000 0xx HCLK not divided
I think I know what's going on here:
If we set the clock to 72mhz we get this panic:
panicked at 'assertion failed: rvr < (1 << 24)', src/timer.rs:268:9
The line before that one sets rvr
as:
let rvr = self.clk.0 / timeout.into().0 - 1;
If I set the count down frequency to 10.hz()
I don't get this panic anymore. It looks like it wants the hclk
(which should be clk.0
means) divided by the timeout (in our case, 1) to be less than 16777217 ((1 << 24) + 1
).
@pedrovanzella The SysTick
counter can only from 24 bits down and it does this with clock frequency by (implementation) default. At 72MHz this gives you a maximum interval time of 0.233s (or 1.864s if you change the SysTick clock to be HCLK/8 instead). If you need longer countdowns you need to set it to a lower value and add up the number of cycles yourself. Or you use the delay functions instead which will do this for you.
@therealprof That makes total sense. Thanks for the explanation!
Sorry for a possibly really dumb question but can't seem to figure it out, in the
blinky.rs
example if I changeto
it continues to work but if I additionally set any other frequency, e.g.
it stops working.
I'm trying to figure out how to explicitly create a config like
rcc_clock_setup_in_hse_8mhz_out_72mhz
from https://github.com/libopencm3/libopencm3/blob/master/lib/stm32/f1/rcc.c#L845Thanks!