Code Monkey home page Code Monkey logo

ch32-hal's Introduction

ch32-hal

Demo Code Github Actions

Rust HAL(Hardware Abstraction Layer) crate for WCH's 32-bit RISC-V microcontrollers.

This HAL crates is the Embassy framework driver for WCH's 32-bit RISC-V microcontrollers.

This HAL crates uses the metapac approach to support multiple chips in the same crate. The metapac is maintained in the ch32-rs/ch32-data repository, published as a crate ch32-metapac.

Keypoints:

  • Embassy support
  • All-in-one metapac for peripheral register access, check ch32-data for more
  • All-in-one HAL crate, no need to create a new crate for each chip
  • Async drivers, with async/await support, DMA support
  • Write once, run on all supported chips(should be)

Supported Devices and Peripherals

Currently, supported chips are listed in Cargo.toml as feature flags, others should work if you are careful as most peripherals are similar enough.

For a full list of chip capabilities and peripherals, check the ch32-data repository.

Family Status Embassy RCC GPIO UART* SPI* I2C ADC Timer(PWM) EXTI* RTC DMA* Delay Others
V2/V3 RNG, SDIO
V1
V0
X0
L1
CH641 N/A ISP
CH643 TODO
  • ✅ : Expected to work
  • ❓ : Not tested
  • * marks the async driver
  • TODO: I haven't got a dev board yet, help-wanted
  • N/A: Not available

TODOs

This section lists some key items that are not implemented yet. And should be noted when using this crate.

  • PLL2 for CH32V3
  • DMA2 for CH32V3 (requires special handling of high DMA channels)

Coming New Chips - Help Wanted

  • CH32V002 / CH32V004 / CH32V005 / CH32V006 / CH32V007 / CH32M007, Qingke V2C
  • CH645, USB HUB, SerDes (V4C)
  • CH564, USBHS, 100M Ethernet (V4J)

Built with ch32-hal ✨

This is a list for awesome projects that are built using ch32-hal

  • ... not yet :(

Minimum supported Rust version(MSRV)

This project is developed with a recent nightly version of Rust compiler. And is expected to work with beta versions of Rust.

Feel free to change this if you did some testing with some version of Rust.

Contributing

All kinds of contributions are welcome.

  • Share your project at Discussions
    • if your project is an open-source project, consider adding it to the list above
  • README and Documentation, including doc comments in code
  • Writing demo code for peripherals
  • Revising the peripheral definitions at ch32-data
  • Adding new peripheral drivers - This is difficult to make it compatible with all chips, but you can try.
  • ...

License

This project is licensed under the MIT or Apache-2.0 license, at your option.

ch32-hal's People

Contributors

andelf avatar 9names avatar marcuss2 avatar romainreignier avatar marti157 avatar

Stargazers

Cheng Ho Ming, Eric avatar Félix Saparelli avatar  avatar  avatar Zoltán Berkes avatar 椰格 avatar TT avatar Ertuğrul avatar hgl10 avatar Rollge avatar Marcus Ramse avatar Fadeevich avatar  avatar fangxx3863 avatar のヮの avatar Jonathan Moore avatar RaisCui avatar Zhazha_JiaYiZhen avatar yihong avatar Choi Jongkook avatar Honsun Zhu avatar Citrus avatar  avatar  avatar HaoboGu avatar Damien Goosse avatar Sinan Bir avatar Rafael Bachmann avatar Martin Ribelotta avatar Decaday avatar Howard_Lyu avatar Alexey Lavrenuke avatar Allen avatar 0x11 avatar icode avatar Bethune avatar David Richmond avatar Zh_Jk avatar a_p_u_r_o avatar intent avatar Dickless avatar Andreas Gnau avatar  avatar 第二扩展 avatar Shreyas Murali avatar salalaika avatar jershell avatar CuprumWangzuo avatar  avatar Harry Brooke avatar onenewcode avatar

Watchers

 avatar Andreas Gnau avatar David Richmond avatar Zoltán Berkes avatar  avatar Yilin Sun avatar Harry Brooke avatar

ch32-hal's Issues

Is there an approach to connect ethernet (wchnet)?

Hello!
This project is awesome and must be driven forward. I have successfully port my interrupt switch logic from EmbeetleIDE (c) to this format and rust. It is much cleaner and it consumes less current. Now i am facing the final task: to send short mqtt messages from the ch32v307 (CH32V307V-R1-1v0). I already have it working in an Embeetle project in c, but now I want to use ethernet with rust and this embassy. I've already read a lot about embassy-net(-driver/-channel etc.), but haven't found the right solution for me.
I think I can also just include the wch-ethernet library and use it, but I'm really looking for the right way to do it.
Does anyone have an idea or even a solution?

Board: https://github.com/openwch/ch32v307/tree/main/SCHPCB/CH32V307V-R1-1v0
Ethernet example: https://github.com/openwch/ch32v307/tree/main/EVT/EXAM/ETH/MQTT
Ethernet Library: https://github.com/openwch/ch32v307/tree/main/EVT/EXAM/ETH/NetLib

Many thanks,
Chris

Add Delay implementation for qingke v4

I have made a draft PR on ch32-hal-template ch32-rs/ch32-hal-template#1 to add the option to not use embassy on the generated template but we would need a Delay implementation for qingke v4.

One could use this:

qingke::riscv::asm::delay(10_000_000);

for a template for beginners, I find that a real delay in milliseconds is easier to use.

Can not build on nightly rust // Can't build any embassy example at all!

I'm having a hard time trying to make at least one embassy example work. Unfortunately, I confirmed that none of the official examples worked, event with the newer cargo-generate template (ch32-hal-template). According to other issues and discussions in this repository, it appears that this problem is unlikely to be affecting every developer! probably proc-macro incompatibilities across nightly revisions!

The error messages bellow were received after trying to build examples/ch32v003/src/bin/embassy_blinky.rs with cargo build --release --bin embassy_blinky.rs or cargo build --bin embassy_blinky.rs and I confirmed that I'm receiving the same error messages with every other embassy example regardless of the target device.

  • nightly-x86_64-unknown-linux-gnu - rustc 1.81.0-nightly (59e2c01c2 2024-06-17)
  • extracted the download from https://github.com/ch32-rs/ch32-hal (current-rev: 56de16c) as it is, and inspected the the examples from their current directories. the non embassy examples I tested worked perfectly.

Build errors

error: item does not constrain `blink::Fut::{opaque#0}`, but has it in its signature
  --> src/bin/embassy_blinky.rs:11:1
   |
11 | #[embassy_executor::task(pool_size = 2)]
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |
   = note: consider moving the opaque type's declaration and defining uses into a separate module
note: this opaque type is in the signature
  --> src/bin/embassy_blinky.rs:11:1
   |
11 | #[embassy_executor::task(pool_size = 2)]
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   = note: this error originates in the attribute macro `embassy_executor::task` (in Nightly builds, run with -Z macro-backtrace for more info)
error: item does not constrain `__embassy_main::Fut::{opaque#0}`, but has it in its signature
  --> src/bin/embassy_blinky.rs:23:1
   |
23 | #[embassy_executor::main(entry = "qingke_rt::entry")]
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |
   = note: consider moving the opaque type's declaration and defining uses into a separate module
note: this opaque type is in the signature
  --> src/bin/embassy_blinky.rs:23:1
   |
23 | #[embassy_executor::main(entry = "qingke_rt::entry")]
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   = note: this error originates in the attribute macro `::embassy_executor::task` (in Nightly builds, run with -Z macro-backtrace for more info)

More Details from Rust Analyzer

proc-macro panicked: failed to load macro: Failed to get file metadata for /home/developer/dev/ch32-hal/examples/ch32v003/target/debug/deps/libembassy_executor_macros-ca73f4ef56da3f51.so: No such file or directory (os error 2)rust-analyzer[macro-error](https://rust-analyzer.github.io/manual.html#macro-error)

Motor encoder // Fast EXTI

Good morning.
Firstly I would like to thank you for this great library.
I'm implementing a motor driver using this lib as a foundation.

Now I have to read the encoder, which consist of 4 wires on which I have to listen to changes (fast changes. Like 40khz). Because of that I don't think the correct way to do this is to get 4 exti-input, await on any change, select them with futures::select and then read what actually changed.
This approach is unstable because rely on embassy task executor, and from one CPU and another could elapse lots of cycles.

Another approach could be to use an embassy interrupt driven executor, but I think isn't supported for this architecture.

Another approach could be to override the exti interrupts handler(if it is possible). But with this I risk to break the other exti interrupts.

In the end I could even remove embassy and implement what I need from scratch, but of course it is one "reinvent thr wheel" approach.

Let me know if I haven't listed all approaches, or if there is one clear winner in your mind.

Keep on the great work👍

How to check final binary size?

Cargo build generates an ELF executable file as a output format which contains many additional data that will not be transferred to the CH32XXX chip. Is there a way for me to know the exact size of my firmware binary so I can keep track of how much flash is being used?

So far I found that cargo bloat can give me the size of the .text section of the binary's ELF format. Is there a better way?

V003:Stuck at initializing UartTx with PC0 pin

I'm using CH32V003F4P6.

let p = ch32_hal::init(Default::default());
println!("initialize uart tx");
let mut uart = UartTx::new(p.USART1, p.PC0, Default::default()).unwrap();
println!("finished initializing uart");

This prints only initialize uart tx.
Note that it's not due to panic caused by unwrap() that finished initializing uart is not printed.
I tested code and found it stuck at this line in UartTx::new_inner().

And I also found PD5 works fine.

let p = ch32_hal::init(Default::default());
println!("initialize uart tx");
let mut uart = UartTx::new(p.USART1, p.PD5, Default::default()).unwrap();
println!("finished initializing uart");

This code prints.

initialize uart tx
finished initializing uart

And it works fine for me now.

CH32V003F4P6 pinouts diagram from datasheet p.10 says PC0 can be UTX_(I don't know what this _ means, though), so I think it can be used for UartTx(and it can compile with PC0, so you expect it to be used?).
Let me correct if I'm wrong:)

USART transmit is clipped to 500kbaud

CH32V003F4U6, nanoCHV32003 v1.0

If the user tries to set uart_config.baudrate above 500_000, the USART still only transmits at 500kbaud. Datasheet and usart/mod.rs indicate 3 Mbps should be possible. It may be a clocking problem with my usage of hal::Config::default().

#![no_std]
#![no_main]
#![feature(type_alias_impl_trait)]

use embassy_executor::Spawner;
use embassy_time::Timer;
use hal::gpio::{AnyPin, Level, Output, Pin};
//use hal::println;
use ch32_hal::usart::UartTx;
use {ch32_hal as hal, panic_halt as _};

use heapless::String;

#[embassy_executor::task]
async fn blink(pin: AnyPin, interval_ms: u64) {
    let mut led = Output::new(pin, Level::Low, Default::default());

    loop {
        led.set_high();
        Timer::after_millis(interval_ms).await;
        led.set_low();
        Timer::after_millis(interval_ms).await;
    }
}

#[embassy_executor::main(entry = "qingke_rt::entry")]
async fn main(spawner: Spawner) -> ! {
    let p = hal::init(hal::Config::default());
    hal::embassy::init();


    let mut uart_config: ch32_hal::usart::Config = Default::default();

    uart_config.baudrate = 500000;

    let mut uart = UartTx::new_blocking(p.USART1, p.PD0, uart_config).unwrap();

    // Adjust the LED GPIO according to your board
    spawner.spawn(blink(p.PD6.degrade(), 100)).unwrap();

    loop {
        Timer::after_millis(100).await;
        uart.blocking_write(b"Hello world!\r\n").unwrap();
    }
}

V003: is i2c ready?

Hi,
Thank you for this nice work, I understand that this is a work in progress.
But is the i2c supposed to work on the CH32V003?
I have tried a simple program but the system hangs in the I2c::new() part (I can see the println logs)):

#![no_std]
#![no_main]
#![feature(type_alias_impl_trait)]

use hal::dma::NoDma;
use hal::i2c::I2c;
use hal::println;
use hal::time::Hertz;
use qingke::riscv;
use {ch32_hal as hal, panic_halt as _};

#[qingke_rt::entry]
fn main() -> ! {
    let mut config = hal::Config::default();
    config.clock = hal::rcc::Config::SYSCLK_FREQ_48MHZ_HSE;
    let p = hal::init(config);
    hal::debug::SDIPrint::enable();

    println!("i2c test");

    // I2C pins
    let i2c_sda = p.PC1;
    let i2c_scl = p.PC2;

    println!("init i2c...");
    // Initialize i2c peripheral
    let i2c = I2c::new(
        p.I2C1,
        i2c_scl,
        i2c_sda,
        NoDma,
        NoDma,
        Hertz::khz(100),
        Default::default(),
    );
    println!("Done");
    loop {}
}

I have noticed that there is no example with i2c for the v003 so it might not be ready yet?
I have tried to debug with minichlink -G and gdb but without success, my breakpoint in main is never reached. How do you debug the ch32 ?

V307: not running

I have tried several examples of the CH32V307 on a "CH32V307 EVT by SCDZ" board:

image

But the programs are not running (not blinks with blinky.rs and no output with sdi_print.rs).
I have tried to change the HSI/HSE settings while initializing the hal but nothing changed.
I the V307 supposed to work already? Or maybe a regression introduced with recent changes?
I have pulled the ch32-metapac from the prebuilt repo.
I have tried the blink.c example from ch32v003fun and it works.

It might be interesting to enable the "Discussions" on this repo to avoid opening issues for these kind of newbie questions.

Thanks

Hangs with default SYSTICK time driver

This is caused by the fact that the 64-bit timer is implemented via two 32-bit words. So under some conditions, a lower-than-current CMP value is written.

Missing instructions for how to build and deploy an example application

Hiya,

I've got a CH32V203C8T6 and I'm really interested in exploring what the Embassy framework has to offer (it looks like an awesome alternative to running a rtos).

However, I'm struggling to get one of the example applications to work. They compile, just fine, but when I deploy them - they don't seem to do anything (ie: blinky doesn't blink) and I've tried all the other example applications.

I'm not very familiar with Rust (but I'm using this project as an excuse to explore it).

Here's what I've done so far (most of which was taken from #3 ):

rustup default nightly
rustup target add riscv32imac-unknown-none-elf

cd examples/ch32v203
cargo build --target riscv32imac-unknown-none-elf --release
# on the ch32v2, I hold the power + reset, then release reset and power
wchisp flash target/riscv32imac-unknown-none-elf/release/blinky
# no blinking on the ch32v2 :(

I've also changed this line to refer to ch32v203c8t6 and recompiled blinky... and again... nothing blinked.

Am I missing something? Or could it be that the example code doesn't work with my chip (for whatever reason).

Thanks for the help! I'm sure it'll help others too :)

[BUG] Trait bound not satisfied for usbd-hid-macros crate

Ran into an issues with building and testing the examples for the ch32v203. This is what I'm getting when I try to run cargo build --bin blinky.

error[E0277]: the trait bound `usbd_hid_descriptors::MainItemKind: From<std::string::String>` is not satisfied
   --> /home/ronin/.cargo/registry/src/index.crates.io-6f17d22bba15001f/usbd-hid-macros-0.6.0/src/spec.rs:512:43
    |
512 |             self.set_item(name, item_kind.into(), settings, bits, quirks);
    |                                           ^^^^ the trait `From<std::string::String>` is not implemented for `usbd_hid_descriptors::MainItemKind`, which is required by `std::string::String: Into<_>`
    |
    = help: the trait `From<&str>` is implemented for `usbd_hid_descriptors::MainItemKind`
    = help: for that trait implementation, expected `&str`, found `std::string::String`
    = note: required for `std::string::String` to implement `Into<usbd_hid_descriptors::MainItemKind>`

   Compiling futures-util v0.3.30
For more information about this error, try `rustc --explain E0277`.
error: could not compile `usbd-hid-macros` (lib) due to 1 previous error
warning: build failed, waiting for other jobs to finish...

It's coming from the GroupSpec Impl in the USBD HID macros crate.

Limitations to PWM frequency?

I don't know if the following is an issue specific to the implementation in this HAL, or that it is a limitation in the chip, so please let me know if this issue is in the wrong place.

For a project in which I am sending 38 kHz NEC messages on a CH32V003F4P6 dev board, I am using SimplePWM to generate a 38 kHz PWM signal and then modulate this by calling pwm.enable and pwm.disable, as follows:

    let mut pwm = SimplePwm::new(
        p.TIM1,
        None,
        None,
        None,
        Some(pin),
        Hertz::khz(38),
        CountingMode::default(),
    );
    let ch = hal::timer::Channel::Ch4;

    // Futher, in the loop to send bits:
    pwm.enable(ch);
    Delay.delay_us(563);
    pwm.disable(ch);
    if bit == 0 {
        Delay.delay_us(563);
    } else {
        Delay.delay_us(1688);
    }

When looking at an oscilloscope connected to the output pin, it looks as follows:
pic_49_1
pic_49_2

Is this a limitation of the CH32V003? That seems unlikely to me, given that the clock of a CH32V003 is about 1000 times higher than the signal frequency? Did I configure the PWM wrong?

I see that in the WS2811 example the signal is bitbanged in code as well, was that done for the same reason?

If any additional information is needed, please let me know :) And thanks for the great work on this project!

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.