~ruther/simple-clock

3f2d59f3bdd0ca569426cd9c9c2dd672852d77cb — František Boháček 1 year, 10 months ago dc38bc1
feat(tests): add full checkup testing peripherals

Tests all peripherals, observation should point
out to where an error is, if any.
A tests/full_checkup/.cargo/config => tests/full_checkup/.cargo/config +8 -0
@@ 0,0 1,8 @@
[target.thumbv7m-none-eabi]
runner = 'probe-run --chip STM32F103C8'
rustflags = [
  "-C", "link-arg=-Tlink.x",
]

[build]
target = "thumbv7m-none-eabi"

A tests/full_checkup/.gitignore => tests/full_checkup/.gitignore +8 -0
@@ 0,0 1,8 @@
/target


# Added by cargo
#
# already existing elements were commented out

#/target

A tests/full_checkup/Cargo.toml => tests/full_checkup/Cargo.toml +13 -0
@@ 0,0 1,13 @@
[package]
name = "full_checkup"
version = "0.1.0"
edition = "2021"

[dependencies]
cortex-m = "0.7.7"
cortex-m-rt = "0.7.3"
embedded-hal = "0.2.7"
nb = "1.1.0"
panic-halt = "0.2.0"
stm32f1xx-hal = { version = "0.10.0", features = ["rt", "stm32f103", "medium"] }
you-can = "0.0.14"

A tests/full_checkup/config.gdb => tests/full_checkup/config.gdb +41 -0
@@ 0,0 1,41 @@
# GDB script for loading and running programs in STM32 Blue Pill.
# This file used to be .gdbinit, which could not be autoloaded due to autoloading security in GDB.

# Send GDB commands to OpenOCD, which listens on port 3333.  Extend the timeout.
target ext :3333

# Disable all messages.
set verbose off
set complaints 0
set confirm off
set exec-done-display off
show exec-done-display
set trace-commands off
set debug displaced off
set debug expression 0
set debug frame 0
set debug infrun 0
set debug observer 0
set debug overload 0
set pagination off
set print address off
set print symbol-filename off
set print symbol off
set print pretty off
set print object off
set debug parser off
set debug remote 0

# Print demangled symbols by default.
set print asm-demangle on

# Enable ARM semihosting to show debug console output in OpenOCD console.
monitor arm semihosting enable

monitor reset init
monitor sleep 50
monitor halt
monitor sleep 50

load
continue

A tests/full_checkup/memory.x => tests/full_checkup/memory.x +6 -0
@@ 0,0 1,6 @@
/* Linker script for the STM32F103C8T6 */
MEMORY
{
  FLASH : ORIGIN = 0x08000000, LENGTH = 64K
  RAM : ORIGIN = 0x20000000, LENGTH = 20K
}

A tests/full_checkup/src/main.rs => tests/full_checkup/src/main.rs +170 -0
@@ 0,0 1,170 @@
#![no_std]
#![no_main]

use core::convert::Infallible;
use embedded_hal::digital::v2::{OutputPin, InputPin};
use panic_halt as _;

use nb::block;

use cortex_m_rt::entry;
use stm32f1xx_hal::{pac, prelude::*, timer::{Timer, Tim1NoRemap, Tim2NoRemap, Tim3NoRemap, PwmChannel}, rtc::Rtc};

#[entry]
fn main() -> ! {
   // Get access to the core peripherals from the cortex-m crate
    let cp = cortex_m::Peripherals::take().unwrap();
    // Get access to the device specific peripherals from the peripheral access crate
    let dp = pac::Peripherals::take().unwrap();

    // Take ownership over the raw flash and rcc devices and convert them into the corresponding
    // HAL structs
    let mut pwr = dp.PWR;
    let mut flash = dp.FLASH.constrain();
    let rcc = dp.RCC.constrain();
    let mut backup_domain = rcc.bkp.constrain(dp.BKP, &mut pwr);

    let mut rtc = Rtc::new(dp.RTC, &mut backup_domain);

    // Freeze the configuration of all the clocks in the system and store the frozen frequencies in
    // `clocks`
    let clocks = rcc
        .cfgr
        .use_hse(8.MHz())
        .sysclk(24.MHz())
        .pclk1(24.MHz())
        .pclk2(24.MHz())
        .freeze(&mut flash.acr);

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

    let (_, pb3, pb4) = afio.mapr.disable_jtag(gpioa.pa15, gpiob.pb3, gpiob.pb4);

    let mut led1 = gpiob.pb12.into_open_drain_output(&mut gpiob.crh);
    let mut led2 = gpiob.pb11.into_open_drain_output(&mut gpiob.crh);
    let mut led3 = gpiob.pb1.into_open_drain_output(&mut gpiob.crl);
    let mut led4 = gpiob.pb0.into_open_drain_output(&mut gpiob.crl);

    let mut leds: [&mut dyn OutputPin<Error = Infallible>; 4] = [&mut led1, &mut led2, &mut led3, &mut led4];

    let btn1 = gpiob.pb15.into_pull_down_input(&mut gpiob.crh);
    let btn2 = gpiob.pb14.into_pull_down_input(&mut gpiob.crh);
    let btn3 = gpiob.pb13.into_pull_down_input(&mut gpiob.crh);
    let btn4 = gpioc.pc13.into_floating_input(&mut gpioc.crh);

    let btns: [&dyn InputPin<Error = Infallible>; 4] = [&btn1, &btn2, &btn3, &btn4];

    let mut a = gpiob.pb10.into_open_drain_output(&mut gpiob.crh);
    let mut b = gpiob.pb2.into_open_drain_output(&mut gpiob.crl);
    let mut c = gpiob.pb8.into_open_drain_output(&mut gpiob.crh);
    let mut d = gpiob.pb6.into_open_drain_output(&mut gpiob.crl);
    let mut e = gpiob.pb9.into_open_drain_output(&mut gpiob.crh);
    let mut f = pb3.into_open_drain_output(&mut gpiob.crl);
    let mut g = pb4.into_open_drain_output(&mut gpiob.crl);
    let mut dpp = gpiob.pb7.into_open_drain_output(&mut gpiob.crl);

    let mut segments: [&mut dyn OutputPin<Error = Infallible>; 8] = [&mut a, &mut b, &mut c, &mut d, &mut e, &mut f, &mut g, &mut dpp];

    let dig1 = gpioa.pa6.into_alternate_open_drain(&mut gpioa.crl);
    let dig2 = gpioa.pa3.into_alternate_open_drain(&mut gpioa.crl);
    let dig3 = gpioa.pa7.into_alternate_open_drain(&mut gpioa.crl);
    let dig4 = gpioa.pa8.into_alternate_open_drain(&mut gpioa.crh);
    let dig5 = gpioa.pa9.into_alternate_open_drain(&mut gpioa.crh);
    let dig6 = gpioa.pa2.into_alternate_open_drain(&mut gpioa.crl);
    let dig7 = gpioa.pa10.into_alternate_open_drain(&mut gpioa.crh);
    let dig8 = gpioa.pa1.into_alternate_open_drain(&mut gpioa.crl);

    let tim1 = Timer::new(dp.TIM1, &clocks);
    let tim2 = Timer::new(dp.TIM2, &clocks);
    let tim3 = Timer::new(dp.TIM3, &clocks);

    let pins1 = (dig4, dig5, dig7);
    let pwm1 = tim1
        .pwm_hz::<Tim1NoRemap, _, _>(pins1, &mut afio.mapr, 500.Hz());

    let pins2 = (dig8, dig6, dig2);
    let pwm2 = tim2
        .pwm_hz::<Tim2NoRemap, _, _>(pins2, &mut afio.mapr, 500.Hz());

    let pins3 = (dig1, dig3);
    let pwm3 = tim3
        .pwm_hz::<Tim3NoRemap, _, _>(pins3, &mut afio.mapr, 500.Hz());

    let (mut dig4, mut dig5, mut dig7) = pwm1.split();
    let (mut dig8, mut dig6, mut dig2) = pwm2.split();
    let (mut dig1, mut dig3) = pwm3.split();

    let mut digits: [&mut dyn _embedded_hal_PwmPin<Duty = u16>; 8] = [ &mut dig1, &mut dig2, &mut dig3, &mut dig4, &mut dig5, &mut dig6, &mut dig7, &mut dig8 ];
    for digit in digits.iter_mut() {
        // has to be enabled, when disabled, 0 is outputted, meaning digit is turned on...
        digit.enable();
        digit.set_duty(0xFFFF);
    }

    // Configure the syst timer to trigger an update every second
    let mut timer = Timer::new(dp.TIM4, &clocks).counter_hz();
    timer.start(1.Hz()).unwrap();

    let mut led_index: usize = 0;
    let mut display_stage: bool = false;
    let mut digit_index: usize = 0;
    let mut segment_index: usize = 0;
    loop {
        for (i, led) in leds.iter_mut().enumerate() {
            if i == led_index {
                led.set_low().unwrap();
            } else {
                led.set_high().unwrap();
            }
        }

        for (i, btn) in btns.iter().enumerate() {
            if btn.is_high().unwrap() {
                leds[i].set_low().unwrap(); // turn on led that is next to the button
            }
        }

        for (i, digit) in digits.iter_mut().enumerate() {
            if i == digit_index {
                digit.set_duty(0);
            } else {
                digit.set_duty(0xFFFF);
            }
        }

        if display_stage {
            for (i, segment) in segments.iter_mut().enumerate() {
                if i == segment_index {
                    segment.set_low().unwrap();
                } else {
                    segment.set_high().unwrap();
                }
            }
        } else {
            for segment in segments.iter_mut() {
                segment.set_low().unwrap();
            }
        }

        led_index = (led_index + 1) % leds.len();

        if display_stage {
            segment_index = (segment_index + 1) % segments.len();
            if segment_index == 0 {
                digit_index = (digit_index + 1) % digits.len();
            }
        } else {
            digit_index = (digit_index + 1) % digits.len();
            segment_index = 0;
        }

        if segment_index == 0 && digit_index == 0 {
            display_stage = !display_stage;
        }

        block!(timer.wait()).unwrap();
    }
}

Do not follow this link