Giter Club home page Giter Club logo

stm32wlxx-hal's Introduction

stm32wlxx-hal

CI stable-docs nightly-docs crates.io rustc

Embedded rust HAL (hardware abstraction layer) for the STM32WL series.

This is still in development, the code that exists today covers basic usage of:

  • SubGHz LoRa TX + RX
  • SubGHz (G)FSK TX + RX
  • SPI
  • GPIO
  • UART
  • I2C
  • Low-power timers
  • ADC
  • DAC
  • PKA ECDSA signing + verification
  • Secure random number generation
  • AES ECB encryption + decryption
  • RTC date and time

Usage

[dependencies.stm32wlxx-hal]
version = "0.6.1"
features = [
    # use exactly one to match your target hardware
    "stm32wl5x_cm0p",
    "stm32wl5x_cm4",
    "stm32wle5",
    # optional: use the cortex-m-rt interrupt interface
    "rt",
    # optional: use defmt
    "defmt",
    # optional: enable conversions with embedded-time types
    "embedded-time",
    # optional: use the real time clock (RTC)
    "chrono",
]

Examples

All examples run on the NUCLEO-WL55JC2.

Most examples are written in the form of on-target tests. See testsuite/README.md for details.

There are also simple examples located in the examples crate. These can be run with the run-ex cargo alias:

cargo run-ex gpio-blink

System Level Example

The on-target tests and examples are a good starting point, but they demonstrate features independent of each-other. A system-level example using multiple features simultaneously is provided in a separate repo: stm32wl-lightswitch-demo

Unit Tests

Off-target unit tests use the built-in cargo framework. You must specify the target device as a feature.

cargo test --features stm32wl5x_cm4

Reference Documentation

stm32wlxx-hal's People

Contributors

dependabot[bot] avatar jorgeig-space avatar kolegs avatar lulf avatar maebli avatar martbent avatar newam avatar shakencodes avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

stm32wlxx-hal's Issues

Tracking issue for features

Loose issue to track features I want for my project, may change

Feel free to comment if you want to see features of the HAL not listed here.

  • SUBGHZ #8
    • async editions of everything
  • RCC
    • Restrict user control of clocks
  • HSEM
  • IPCC
  • GPIOs
    • Add all alternate functions
    • Add AnyPin type (maybe?)
    • Add async interface to await a IRQ
  • DMA
    • mem2mem interface
  • ADC
    • Junction temperature measurement
    • Battery level measurement
  • RNG
  • AES
    • ECB
  • PKA
    • ECDSA sign
    • ECDSA verify
  • Timers
  • RTC
  • I2C
  • UART
  • SPI
    • device main
    • async API (DMA only)
  • electronic signature

Lora P2P communication

Hi,

I am a rust embedded newbie and I am trying to configure Lora P2P communication between two NUCLEO-WL55JC boards. But I got a problem with even sending any data. When I check radio.irq_status() after calling set_tx I get ExecutionFailure, which means that the command was accepted but the data couldn't be sent. Basically I never hit TX done or Other IRQs on debugger.

Is there any example of Lora configuration available for a reference?

Below configuration code:

    let (ctrl1, ctrl2, ctrl3) = cortex_m::interrupt::free(|cs| {
        (
            Output::default(gpioc.c4, cs),
            Output::default(gpioc.c5, cs),
            Output::default(gpioc.c3, cs),
        )
    });

    let mut radio_switch = radio_switch::RadioSwitch::new(ctrl1, ctrl2, ctrl3);

    const TX_BUF_OFFSET: u8 = 128;
    const RX_BUF_OFFSET: u8 = 0;

    const DATA_LEN: u8 = 24_u8;
    const PREAMBLE_LEN: u16 = 12;

    const RF_FREQ: RfFreq = RfFreq::F433;

    const LORA_PACKET_PARAMS: LoRaPacketParams = LoRaPacketParams::new()
        .set_crc_en(true)
        .set_preamble_len(PREAMBLE_LEN)
        .set_payload_len(DATA_LEN)
        .set_invert_iq(false)
        .set_header_type(HeaderType::Fixed);

    const LORA_MOD_PARAMS: LoRaModParams = LoRaModParams::new()
        .set_bw(LoRaBandwidth::Bw125)
        .set_cr(CodingRate::Cr45)
        .set_ldro_en(false)
        .set_sf(SpreadingFactor::Sf7);

    const PA_CONFIG: PaConfig = PaConfig::LP_14;

    const TX_PARAMS: TxParams = TxParams::LP_14.set_ramp_time(RampTime::Micros40);

    let mut radio = SubGhz::new(dp.SPI3, &mut dp.RCC);

    radio.set_smps_clock_det_en(true).unwrap();
    radio.set_smps_drv(hal::subghz::SmpsDrv::Milli60).unwrap();

    radio.set_standby(hal::subghz::StandbyClk::Rc).unwrap();

    radio.set_hse_in_trim(HseTrim::from_raw(0x20)).unwrap();
    radio.set_hse_out_trim(HseTrim::from_raw(0x20)).unwrap();

    radio
        .set_regulator_mode(hal::subghz::RegMode::Smps)
        .unwrap(); // Use DCDC

    radio
        .set_buffer_base_address(TX_BUF_OFFSET, RX_BUF_OFFSET)
        .unwrap();

    radio.set_pa_config(&PA_CONFIG).unwrap();
    radio.set_pa_ocp(hal::subghz::Ocp::Max60m).unwrap();
    radio.set_tx_params(&TX_PARAMS).unwrap();

    radio
        .set_packet_type(hal::subghz::PacketType::LoRa)
        .unwrap();
    radio
        .set_lora_sync_word(hal::subghz::LoRaSyncWord::Public)
        .unwrap();
    radio.set_lora_mod_params(&LORA_MOD_PARAMS).unwrap();
    radio.set_lora_packet_params(&LORA_PACKET_PARAMS).unwrap();
    radio.calibrate_image(CalibrateImage::ISM_430_440).unwrap();
    radio.set_rf_frequency(&RF_FREQ).unwrap();

    // unsafe {
    //     subghz::unmask_irq();
    // }
    // Set IRQs
    radio
        .set_irq_cfg(
            &CfgIrq::new()
                .irq_enable_all(Irq::RxDone)
                .irq_enable_all(Irq::TxDone)
                .irq_enable_all(Irq::Timeout)
                .irq_enable_all(Irq::Err),
        )
        .unwrap();

And transmit dummy data code:

    let mut payload: [u8; 24] = [0u8; 24];
    for i in 0..24 {
        payload[i] = i as u8;
    }

    defmt::info!("Send data");
    radio.write_buffer(TX_BUF_OFFSET, &payload[..]).unwrap();
    radio_switch.set_tx();  // Turn on ctrl1, ctrl2 and ctrl3
    radio.set_tx(Timeout::from_millis_sat(500)).unwrap();

    loop {
        let (status, irq_status) = radio.irq_status().unwrap();
        let mode = status.mode().unwrap();
        let cmd = status.cmd().unwrap();
        radio.clear_irq_status(irq_status).unwrap();
        if irq_status & Irq::TxDone.mask() != 0 {
            // nothing is required upon TX done
            // you may want to put the radio into RX mode after TX completion
            defmt::info!("TX done");
            break;
        } else if irq_status != 0 {
            defmt::info!("Other IRQ")
            // ... handle other IRQs
        }
    }

I am using Msi 48Mhz clock.

Any hints are much appreciated and after figuring it out I plan to share my solution with the others in a form of an example code.

compile

Hi, i want to test your gpio-blink.rs in my module LSM110A (W55JC)...

I am doing on examples folder

$~/stm32wlxx-hal
cd examples
cargo build

image

How i create the hex to burn in my Module ?

I dont want to use the cargo-run

Thanks

Tracking issue for SubGHz commands

5.8.2 Register and Buffer Access

  • Read_Buffer
  • Write_Buffer

Registers

Implementing all these instead of the generic Read_Register and Write_Register commands.

  • SUBGHZ_GBSYNCR - #169
  • SUBGHZ_GPKTCTL1AR - #170
  • SUBGHZ_GWHITEINIRL
  • SUBGHZ_GCRCINIR[H/L]
  • SUBGHZ_GCRCPOLR[H/L]
  • SUBGHZ_GSYNCR[0-7]
  • SUBGHZ_LSYNCR[H/L]
  • SUBGHZ_RNGR[0-3] - skip because we have TRNG peripheral
  • SUBGHZ_RXGAINCR - #166
  • SUBGHZ_PAOCPR
  • SUBGHZ_HSEINTRIMR
  • SUBGHZ_HSEOUTTRIMR
  • SUBGHZ_SMPSC0R- #171
  • SUBGHZ_PCR - #173
  • SUBGHZ_SMPSC2R - #172

5.8.3 Operating Mode Commands

  • Set_Sleep
  • Set_Standby
  • Set_Fs
  • Set_Tx
  • Set_Rx
  • Set_StopRxTimerOnPreamble
  • Set_RxDutyCycle
  • Set_Cad
  • Set_TxContinuousWave
  • Set_TxContinuousPreamble

5.8.4 Sub-GHz radio configuration commands

  • Set_PacketType
  • Get_PacketType
  • Set_RfFrequency
  • Set_TxParams
  • Set_PaConfig
  • Set_TxRxFallbackMode
  • Set_CadParams
  • Set_BufferBaseAddress
  • (G)FSK Set_ModulationParams
  • LoRa Set_ModulationParams
  • BPSK Set_ModulationParams
  • Generic Set_PacketParams
  • BPSK Set_PacketParams
  • LoRa Set_PacketParams
  • Set_LoRaSymbTimeout

5.8.5 Communication status and information commands

  • Get_Status
  • Get_RxBufferStatus
  • (G)FSK Get_PacketStatus
  • LoRa Get_PacketStatus
  • Get_RssiInst
  • (G)FSK Get_Stats
  • LoRa Get_Stats
  • Reset_Stats

5.8.6 IRQ interrupt commands

  • Cfg_DioIrq
  • Get_IrqStatus
  • Clr_IrqStatus

5.8.7 Miscellaneous commands

  • Calibrate
  • CalibrateImage
  • Set_RegulatorMode
  • Get_Error
  • Clr_Error

5.8.8 Set_TcxoMode command

  • Set_TcxoMode

how to access i2c

Hi @newAM!

Thanks for your work on this library, it's quite helpful!

Sadly, I'm struggling to get I2C to work. I'm quite new to (embedded) rust, so this might just be a small error in my understanding.

Here is some example code

use cortex_m_rt::entry;

use stm32wlxx_hal::{
    pac::{self}, gpio::{PortA}, i2c, embedded_hal::prelude::_embedded_hal_blocking_i2c_Write
};

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

    let gpioa: PortA = PortA::split(dp.GPIOA, &mut dp.RCC);

    let scl = gpioa.a11;
    let sda = gpioa.a12;

    let i2c = cortex_m::interrupt::free(|cs| {
            i2c::I2c2::new(dp.I2C2, (scl, sda), 1500, &mut dp.RCC, true, cs)
        });
    
    i2c.write(0x56, &[0]); //example data

    loop {
        hprintln!("Running!").unwrap();
    }
}

This fails on i2c::I2c2::new with the trait 'gpio::sealed::I2c2Scl' is not implemented for 'A11'.

How can I resolve this?
Thanks in advance for any help you can provide me :)

How to Establish a Continuous LPTIM Peripheral

I would like to use an LPTIM peripheral to track time. To do so I would like it to be in continuous mode so it just fires off the event and then reloads and keeps going. Unfortunately, the start function implementation for the LPTIM peripherals seems to set the mode to Single. How would I go about setting this up for continuous?

Implement InputPin from embedded_hal

edit: found OutputPin, seems like it's just InputPin I can't find

Hi

Apologies if this request doesn't make sense, I am still getting familiar with the ecosystem.

I am trying my hand at writing a generic driver using embedded hal, and I am using a nucleo-wl55jc as a test board. I would like to use the InputPin and OutputPin traits to do so but see that they aren't implemented for Input and Output. Is there a specific reason for this, or should I write a PR?

Thanks

LPUART type mismatch & some other issues about UART peripheral implementation

Hi all,

Sorry for this stupid question, I'm new to Embedded Rust. I'm trying to use this HAL crate with RTIC together to implement a UART-LoRa modem. But so far I just couldn't figure out this issue when I try to enable RXNEIE (receive data register not empty interrupt):

image

Here's the code: https://github.com/huming2207/lowu-basestation/blob/cdf87dbade6c983cbe4c77556b336dfc17320af9/src/bin/app.rs

I've also tried replacing the uart_p to dp.LPUART but still no luck, and Rust compiler complains the exact same error when compiling so it's not a language server or VSCode plugin's false positive. Anyway, may I ask if is there any suggestion on how to get RXNEIE to be set?

Meanwhile I've also got another issue with defmt-serial earlier in July: gauteh/defmt-serial#1

Basically, the author tested his implementation works fine on some other microcontrollers, but it didn't work at all on my RAK3172 (STM32WLE5JC) development kit. I'm not sure if this issue is related to the USART/LPUART implementation in this crate, but I've brought it here just in case.

Regards,
Jackson

Nitpicks

  • Replace wall-of-text # Safety sections with enumerated check-lists of requirements.
  • Lots of duplicated code across testsuites (fixed in #82)
  • Provide a from_millis, from_nanos, from_secs ect. with subghz::Timeout
  • Normalize meta-access of peripherals for all peripherals (maybe trait these to enforce uniformity?)
    • pub unsafe fn steal() -> Self
    • fn mask_irq()
    • pub unsafe fn unmask_irq()
    • pub unsafe fn pulse_reset(rcc: &mut pac::RCC)
    • pub fn enable_clock(rcc: &mut pac::RCC)
    • pub unsafe fn disable_clock(rcc: &mut pac::RCC)
    • Normalize what new does with regards to clocks, resets, enables, and interrupts

SPI reworks

  • Support bus-secondary mode (and therefore write-only, read-only modes)
  • Rework DMA generic to work more like UART, Spi<SckPin, (MosiPin, MosiDma), (MisoPin, MisoDma)>
  • Deduplicate existing code leveraging macros and traits.

Include Example of UART/DMA usage

I am working to use this crate to drive my LoRa-E5 and right now just trying to get UART comms with DMA running. After a review of the crate, it seems as though all of the low-level DMA bit flipping is happening in the trait impl's. So, to enable DMA transfers, one just needs to enable the tx/rx with a DMA tuple. But, I am confused on the "correct/idiomatic" way to use these trait impl's. Can you provide a simple UART with DMA example, something like a simple echo server.

Specific questions I would look to answer with this would be,

  1. Do I do enable_rx and enable_tx at UART instantiation or just immediately prior to use the Write or Read functions? (This seems like not the case as DMAR and DMAT are set for each of these and I did not think that both could be enabled at the same time)
  2. The way the code is written, it does not seem to be able to pass a vector of u8 to a write function in a non-blocking way. Historically, I would set the memory address of the DMA channel, set the number of transfers, enable, and then walk away and do other things letting the DMA irq tell me when it is done. This does not currently seem possible.

I think an example will help me see how this was intended to be done.

UART Clock frequency when selecting PClk returns HClk frequency

When PClk is selected as the clock source, the UARTs use the following clocks (according to STM32CubeMX, the ref manual is not clear as it just says PClkn):

  • LPUART1: PClk1
  • USART1: PClk2
  • USART2: PClk1

However, in the uart.rs::UartX.clock_hz function used to calculate the baudrate, the hclk3 function is used to return the HClk frequency for PClk. If the APB scaler is used, this will be the wrong frequency.

I'm preparing a PR to correct it.

can not build success

Hi, i clone this code, but it can not build successful.

$ DEFMT_LOG=trace cargo run-ex gpio-blink
error: failed to load manifest for workspace member `/Users/zhangxiang/embedded-worksapce/DLB/Code/stm32wlxx-hal/lora-e5-bsp`

Caused by:
  failed to parse manifest at `/Users/zhangxiang/embedded-worksapce/DLB/Code/stm32wlxx-hal/lora-e5-bsp/Cargo.toml`

Caused by:
  namespaced features with the `dep:` prefix are only allowed on the nightly channel and requires the `-Z namespaced-features` flag on the command-line

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.