Skip to content

Commit 376b057

Browse files
authored
Merge branch 'main' into feat/stable-rustc
2 parents 9816097 + 1f68155 commit 376b057

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

108 files changed

+9536
-6108
lines changed

.cargo/config.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,5 @@
11
[alias]
22
blri = "run --package blri --release --"
3+
4+
[target.'cfg(target_os = "none")']
5+
runner = "cargo blri run"

.github/workflows/Cargo.yml

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,16 +35,35 @@ jobs:
3535
- name: Run tests
3636
run: cargo test -p ${{ MATRIX.PACKAGE }}
3737

38-
build-bouffalo-hal:
39-
name: Build
38+
build-bouffalo-hal-riscv64:
39+
name: Build for riscv64
4040
needs: fmt
4141
runs-on: ubuntu-latest
4242
strategy:
4343
matrix:
4444
TARGET: [riscv64imac-unknown-none-elf]
45-
TOOLCHAIN: [stable]
46-
EXAMPLES: [gpio-demo, i2c-demo, jtag-demo, lz4d-demo, pwm-demo,
47-
sdcard-demo, sdcard-gpt-demo, spi-demo, uart-demo, uart-async-demo, uart-cli-demo]
45+
# TOOLCHAIN: [stable] # TODO
46+
TOOLCHAIN: [nightly]
47+
EXAMPLES: [gpio-demo, i2c-demo, jtag-demo, lz4d-demo, psram-demo, pwm-demo,
48+
sdcard-demo, sdcard-gpt-demo, sdh-demo, sdh-dma-demo, spi-demo, uart-demo, uart-async-demo, uart-cli-demo]
49+
steps:
50+
- uses: actions/checkout@v4
51+
- uses: actions-rust-lang/setup-rust-toolchain@v1
52+
with:
53+
target: ${{ MATRIX.TARGET }}
54+
toolchain: ${{ MATRIX.TOOLCHAIN }}
55+
- name: Run build
56+
run: cargo build --target ${{ MATRIX.TARGET }} --release -p ${{ MATRIX.EXAMPLES }}
57+
58+
build-bouffalo-hal-riscv32:
59+
name: Build for riscv32
60+
needs: fmt
61+
runs-on: ubuntu-latest
62+
strategy:
63+
matrix:
64+
TARGET: [riscv32imac-unknown-none-elf]
65+
TOOLCHAIN: [nightly]
66+
EXAMPLES: [uart-dma-demo]
4867
steps:
4968
- uses: actions/checkout@v4
5069
- uses: actions-rust-lang/setup-rust-toolchain@v1

Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,11 @@ members = [
1717
"examples/peripherals/uart-demo",
1818
"examples/peripherals/uart-async-demo",
1919
"examples/peripherals/uart-cli-demo",
20+
"examples/peripherals/uart-dma-demo",
2021
"examples/peripherals/sdcard-demo",
2122
"examples/peripherals/sdcard-gpt-demo",
2223
"examples/peripherals/psram-demo",
2324
"examples/peripherals/sdh-demo",
25+
"examples/peripherals/sdh-dma-demo",
2426
]
2527
resolver = "3"

README.md

Lines changed: 62 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,70 @@
1-
# Bouffalo chip Rust Hardware Abstraction Layer (HAL)
1+
# Bouffalo HAL
22

3-
This repository contains `bouffalo-hal` and `bouffalo-rt` packages.
3+
**Rust Hardware Abstraction Layer for Bouffalo chips**
4+
5+
[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
6+
[![License: Mulan PSL v2](https://img.shields.io/badge/License-Mulan%20PSL%20v2-blue.svg)](https://opensource.org/license/mulanpsl-2-0)
7+
[![GitHub Actions Workflow Status](https://img.shields.io/github/actions/workflow/status/rustsbi/bouffalo-hal/Cargo.yml)](https://github.com/rustsbi/bouffalo-hal/actions)
8+
9+
## Overview
10+
11+
This repository contains three main components that provide comprehensive support for Bouffalo chips development in Rust:
12+
13+
- **bouffalo-hal**: Hardware Abstraction Layer for Bouffalo IoT chips, providing safe and efficient interfaces to various peripherals. This component abstracts hardware-specific details and offers a consistent API for interacting with the chip's features.
14+
15+
- **bouffalo-rt**: Runtime support for Bouffalo chips, including the `#[entry]` macro and other essential runtime functionalities. This component handles the low-level initialization required before the main application code runs.
16+
17+
- **blri**: A utility for firmware image verification, patching, and flashing assistance. It helps with the firmware burning process for Bouffalo chips.
18+
19+
Together, these components form a complete ecosystem for embedded development on Bouffalo hardware.
20+
21+
## Features
22+
23+
- Rust-native implementation with memory safety guarantees
24+
- Safe and efficient hardware abstractions
25+
- Support for various peripherals: GPIO, UART, SPI, I2C, PWM, and more
26+
- Rich examples demonstrating peripheral usage
27+
- Seamless integration with the embedded Rust ecosystem
28+
29+
## Examples
30+
31+
<table>
32+
<tr>
33+
<td align="center" width="32%">
34+
<a href="examples/peripherals/uart-cli-demo">UART CLI Demo</a>
35+
<br>
36+
<img src="docs/uart-cli-demo.gif" width="100%" alt="UART CLI Demo">
37+
</td>
38+
<td align="center" width="32%">
39+
<a href="examples/peripherals/pwm-demo">PWM Demo</a>
40+
<br>
41+
<img src="docs/pwm-demo.gif" width="100%" alt="PWM Demo">
42+
</td>
43+
<td align="center" width="32%">
44+
<a href="examples/peripherals/spi-demo">SPI Demo</a>
45+
<br>
46+
<img src="docs/spi-demo.gif" width="100%" alt="SPI Demo">
47+
</td>
48+
</tr>
49+
</table>
50+
51+
You can find all example code in the `examples/` directory.
52+
53+
## Contributing
54+
55+
Contributions are welcome!
56+
57+
For bugs or suggestions, please [submit an issue](https://github.com/rustsbi/bouffalo-hal/issues/new).
58+
59+
To contribute code, please follow our [contribution guidelines](https://github.com/rustsbi/slides/blob/main/2025/reports/Contributing%20to%20RustSBI.md).
460

561
## Minimum supported Rust version
662

763
To compile the `bouffalo-hal` crates, you need at least stable Rust version of `rustc 1.85.0`.
864

965
## License
1066

11-
Project is dual licensed under MIT or Mulan-PSL v2.
12-
13-
```
14-
Copyright (c) 2023 RustSBI Team
15-
bouffalo-hal is licensed under Mulan PSL v2.
16-
You can use this software according to the terms and conditions of the Mulan PSL v2.
17-
You may obtain a copy of Mulan PSL v2 at:
18-
http://license.coscl.org.cn/MulanPSL2
19-
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
20-
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
21-
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
22-
See the Mulan PSL v2 for more details.
23-
```
67+
This project is licensed under either of
68+
69+
- MIT license ([LICENSE-MIT](LICENSE-MIT) or [https://opensource.org/licenses/MIT](https://opensource.org/licenses/MIT))
70+
- Mulan PSL v2 ([LICENSE-MULAN](LICENSE-MULAN) or [https://opensource.org/licenses/MulanPSL-2.0](https://opensource.org/licenses/MulanPSL-2.0))

blri/Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@ clap = { version = "4.5.18", features = ["derive"] }
1111
crc = "3.2.1"
1212
sha2 = "0.10.8"
1313
thiserror = "2.0.3"
14+
inquire = "0.7.5"
15+
serialport = { version = "4.3", default-features = false }
16+
object = "0.36.7"
17+
same-file = "1.0.6"
1418

1519
[dev-dependencies]
1620
tempfile = "3.12.0"

blri/src/isp.rs

Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
const GET_BOOT_INFO: u8 = 0x10;
2+
const DEVICE_RESET: u8 = 0x21;
3+
const ERASE_FLASH: u8 = 0x30;
4+
const WRITE_FLASH: u8 = 0x31;
5+
6+
#[derive(thiserror::Error, Debug)]
7+
pub enum IspError {
8+
#[error("Wrong response length: {wrong_length}")]
9+
ResponseLength { wrong_length: usize },
10+
}
11+
12+
pub trait IspCommand {
13+
type Response;
14+
const COMMAND: u8;
15+
const RESPONSE_PAYLOAD: bool;
16+
fn data_size(&self) -> usize;
17+
fn write_packet_data(&self, buf: &mut [u8]);
18+
fn parse_response(bytes: &[u8]) -> Result<Self::Response, IspError>;
19+
}
20+
21+
// Ref: https://github.com/pine64/blisp/blob/e45941c45e2418b2bb7e3dab49468a8f4d132439/include/blisp.h#L26
22+
#[repr(C)]
23+
pub struct BootInfo {
24+
pub boot_rom_version: [u8; 4],
25+
_reserved1: [u8; 4],
26+
pub flash_info_from_boot: u32,
27+
pub chip_id: [u8; 6],
28+
_reserved2: [u8; 6],
29+
}
30+
31+
impl BootInfo {
32+
pub fn flash_pin(&self) -> u32 {
33+
(self.flash_info_from_boot >> 14) & 0x1f
34+
}
35+
}
36+
37+
pub struct GetBootInfo;
38+
39+
// Ref: https://github.com/pine64/blisp/blob/e45941c45e2418b2bb7e3dab49468a8f4d132439/lib/blisp.c#L234
40+
impl IspCommand for GetBootInfo {
41+
type Response = BootInfo;
42+
const COMMAND: u8 = GET_BOOT_INFO;
43+
const RESPONSE_PAYLOAD: bool = true;
44+
fn data_size(&self) -> usize {
45+
0
46+
}
47+
fn write_packet_data(&self, buf: &mut [u8]) {
48+
assert!(buf.len() == 0);
49+
// nothing to write
50+
}
51+
fn parse_response(bytes: &[u8]) -> Result<Self::Response, IspError> {
52+
if bytes.len() != 24 {
53+
return Err(IspError::ResponseLength {
54+
wrong_length: bytes.len(),
55+
});
56+
}
57+
Ok(BootInfo {
58+
boot_rom_version: bytes[0..4].try_into().unwrap(),
59+
_reserved1: bytes[4..8].try_into().unwrap(),
60+
flash_info_from_boot: u32::from_le_bytes(bytes[8..12].try_into().unwrap()),
61+
chip_id: bytes[12..18].try_into().unwrap(),
62+
_reserved2: bytes[18..24].try_into().unwrap(),
63+
})
64+
}
65+
}
66+
67+
pub struct DeviceReset;
68+
69+
// Ref: https://github.com/pine64/blisp/blob/e45941c45e2418b2bb7e3dab49468a8f4d132439/lib/blisp.c#L403
70+
impl IspCommand for DeviceReset {
71+
type Response = ();
72+
const COMMAND: u8 = DEVICE_RESET;
73+
const RESPONSE_PAYLOAD: bool = false;
74+
fn data_size(&self) -> usize {
75+
0
76+
}
77+
fn write_packet_data(&self, buf: &mut [u8]) {
78+
assert!(buf.len() == 0);
79+
// nothing to write
80+
}
81+
fn parse_response(bytes: &[u8]) -> Result<Self::Response, IspError> {
82+
if bytes.len() != 0 {
83+
return Err(IspError::ResponseLength {
84+
wrong_length: bytes.len(),
85+
});
86+
}
87+
Ok(())
88+
}
89+
}
90+
91+
#[repr(C)]
92+
pub struct EraseFlash {
93+
start: [u8; 4],
94+
end: [u8; 4],
95+
}
96+
97+
impl EraseFlash {
98+
pub fn new(start_addr: u32, end_addr: u32) -> Self {
99+
Self {
100+
start: start_addr.to_le_bytes(),
101+
end: end_addr.to_le_bytes(),
102+
}
103+
}
104+
}
105+
106+
// Ref: https://github.com/pine64/blisp/blob/e45941c45e2418b2bb7e3dab49468a8f4d132439/lib/blisp.c#L355
107+
impl IspCommand for EraseFlash {
108+
type Response = ();
109+
const COMMAND: u8 = ERASE_FLASH;
110+
const RESPONSE_PAYLOAD: bool = false;
111+
fn data_size(&self) -> usize {
112+
8
113+
}
114+
fn write_packet_data(&self, buf: &mut [u8]) {
115+
assert!(buf.len() == 8);
116+
buf[0..4].clone_from_slice(&self.start);
117+
buf[4..8].clone_from_slice(&self.end);
118+
}
119+
fn parse_response(bytes: &[u8]) -> Result<Self::Response, IspError> {
120+
if bytes.len() != 0 {
121+
return Err(IspError::ResponseLength {
122+
wrong_length: bytes.len(),
123+
});
124+
}
125+
Ok(())
126+
}
127+
}
128+
129+
#[repr(C)]
130+
pub struct WriteFlash<'a> {
131+
start: [u8; 4],
132+
payload: &'a [u8],
133+
}
134+
135+
impl<'a> WriteFlash<'a> {
136+
pub fn new(start_addr: u32, payload: &'a [u8]) -> Self {
137+
Self {
138+
start: start_addr.to_le_bytes(),
139+
payload,
140+
}
141+
}
142+
}
143+
144+
// Ref: https://github.com/pine64/blisp/blob/e45941c45e2418b2bb7e3dab49468a8f4d132439/lib/blisp.c#L372
145+
impl<'a> IspCommand for WriteFlash<'a> {
146+
type Response = ();
147+
const COMMAND: u8 = WRITE_FLASH;
148+
const RESPONSE_PAYLOAD: bool = false;
149+
fn data_size(&self) -> usize {
150+
4 + self.payload.len()
151+
}
152+
fn write_packet_data(&self, buf: &mut [u8]) {
153+
buf[0..4].clone_from_slice(&self.start);
154+
buf[4..].clone_from_slice(&self.payload);
155+
}
156+
fn parse_response(bytes: &[u8]) -> Result<Self::Response, IspError> {
157+
if bytes.len() != 0 {
158+
return Err(IspError::ResponseLength {
159+
wrong_length: bytes.len(),
160+
});
161+
}
162+
Ok(())
163+
}
164+
}

0 commit comments

Comments
 (0)