Cargo.toml hierarchy calls

Trying to learn rust embedded here (blinking using stm32f1x blue pill)!
Searched the internet without answer, pointers/comments/optimizations are welcome!
Wish those experimentations could be of any use in the forum!
Most of the code taken from the internet!

Lets start with an implementation (01) without using libraries!

#![no_std]
#![no_main]

//use panic_halt;  // need to be in the blink file
use cortex_m_rt::entry;

mod stm32_blink01;

#[entry]
fn main() -> ! {
    stm32_blink01::run();  // using bare registers
    //stm32_blink02::run();  // using the stm32f1 pac
    //stm32_blink03::run();  // using the stm32f1 hal
}

So the first implementation!

fn delay(mut dly : u32) {
    while dly > 0 { dly = dly -1; }
}

pub fn run() -> ! {
    let rcc_apb2enr = 0x40021018 as *mut u32;   // ch:8.3.7 RT0008 manual
    let gpioc_crh = 0x40011004 as *mut u32;     // ch:9.2.2
    let gpioc_odr  = 0x4001100C as *mut u32;    // ch:9.2.4

    unsafe {
    // initialization
        *rcc_apb2enr |= 1 << 4; // enable clock on gpioC (bit 4)
        *gpioc_crh |= 1 << 20;  // pc12 as an output 10mhz (set bit 20)
        *gpioc_crh &= !( (1 << 23) | (1 << 22) | (1 << 21) ); // unset bits 21,22,23
    }

    loop {
        unsafe {
            *gpioc_odr |= 1 << 13;      // set bit 13
            delay(50000);
            *gpioc_odr &= !(1 << 13);   // clear bit 13
            delay(50000);
        }
    }
}

I still need on the Cargo.toml those imports!

[dependencies]
panic-halt = "0.2.0"
cortex-m-rt = "0.6.7"

In this case as I don't want to implement a reset handler so I need one of the panic versions!
And as documented I need the cortex-m-rt for the "#[entry]" on the code!
? Is that the minimal requirements to build an embedded program ?

Then I did an pac version (02) of it!

use panic_halt;
use stm32f1::stm32f103 as pac;

pub fn run() -> ! {
    let peripherals = pac::Peripherals::take().unwrap();
    let gpioc = &peripherals.GPIOC;
    let rcc = &peripherals.RCC;

    // enable the GPIO clock for IO port C
    rcc.apb2enr.write(|w| w.iopcen().set_bit()); // bit 4 ch:7.3.7
    gpioc.crh.write(|w| unsafe {// ch:9.2.2
        w.mode13().bits(0b11);  // out mode 50mhz
        w.cnf13().bits(0b00)    // general purpose push-pull
    });

    loop {
        gpioc.odr.write(|w| w.odr13().set_bit());
        cortex_m::asm::delay(2000000);
        gpioc.odr.write(|w| w.odr13().clear_bit());
        cortex_m::asm::delay(2000000);
    }
}

Now I need 2 additional libraries!
Then, questions came!?
Did the stm32f1 should implement the cortex-m functions or import them?
Why should I need it as a dependency?

[dependencies]
panic-halt = "0.2.0"
cortex-m-rt = "0.6.7"
# add to stm32_blink02.rs (using pac crate)
stm32f1 = { version = "0.6.0", features = ["stm32f103", "rt"] }
cortex-m = "0.5.8"  # for using delay

then the last implementation (03) was using the hal version!

use panic_halt as _;
use embedded_hal::digital::v2::OutputPin;
use stm32f1xx_hal::{pac::Peripherals, prelude::*, delay::Delay };

pub fn run() -> ! {

    let cp = cortex_m::Peripherals::take().unwrap();  // core peripherals
    let dp = Peripherals::take().unwrap();  // device peripherals

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

    //  Get GPIO Port C, which also enables the Advanced Peripheral Bus 2 (APB2) clock for Port C.
    let mut gpioc = dp.GPIOC.split(&mut rcc.apb2);

    //  Use Pin PC 13 of the Blue Pill for GPIO Port C. Select Output Push/Pull mode for the pin, which is connected to our LED.
    let mut led = gpioc.pc13.into_push_pull_output(&mut gpioc.crh);

    //  Create a delay timer from the RCC clocks.
    let mut delay = Delay::new(cp.SYST, clocks);

    loop {
        led.set_high().unwrap();
        delay.delay_ms(1_000_u16);
        led.set_low().unwrap();
        delay.delay_ms(1_000_u16);
    }
}

and the Cargo.toml

[dependencies]
panic-halt = "0.2.0"
cortex-m-rt = "0.6.7"
# add to stm32_blink02.rs (using pac crate)
stm32f1 = { version = "0.6.0", features = ["stm32f103", "rt"] }
cortex-m = "0.5.8"  # for using delay
# add to stm32_blink03.rs (using hal crate)
embedded-hal = "0.2.3"
stm32f1xx-hal = { version = "0.6.0", features = ["stm32f103", "rt", "medium"] }

What I didn't understand here is why should I need the embedded_hal? Again as "stm32f1xx_hal" Is an implementation of the "embedded_hal" should inherit all functions from it? As the "pac::Peripherals" could be called from the hal! I am seeing this dont quite work as I thought! Any documentation/comments on how to understand those associations?
Best regards,

You need embedded-hal, because you use it's set_low() and set_high() methods. To call a trait method you need to import the trait first (in this case embedded_hal::digital::v2::OutputPin).

Some HALs or PACs may re-export embedded-hal traits, but they don't have to. If they do you don't necessarily need the embedded-hal dependency.