1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
//! Hardware abstract layer (HAL) for the GD32VF103 microcontroller chip.
//!
//! This is an implementation of `embedded-hal` traits for the GD32VF103, MCU with
//! one RISC-V's RV32IMAC core as well as up to 128 KiB of Flash and 32 KiB of SRAM,
//! produced by GigaDevice Semiconductor Inc.
//!
//! # Usage
//! Add this crate to your dependencies:
//! ```
//! [dependencies]
//! gd32vf103-hal = "0.0"
//! ```
//!
//! # Example
//! ```
//! #![no_std]
//! #![no_main]
//! // choose a panic handler crate
//! extern crate panic_halt;
//! // include this library
//! use gd32vf103_hal::{pac, prelude::*};
//! // use the `riscv_rt` runtime to define entry
//! #[riscv_rt::entry]
//! fn main() -> ! {
//! // Get ownership of device peripherals
//! let dp = pac::Peripherals::take().unwrap();
//! // Constrain RCU register for further use
//! let mut rcu = dp.RCU.constrain();
//! // Split GPIOA into separate pins.
//! // You need a mutable reference of APB2 struct to initialize GPIOA,
//! // so we offer `&mut rcu.apb2` as a parameter here.
//! let mut gpioa = dp.GPIOA.split(&mut rcu.apb2);
//! // Change the state of `pa1` into push-pull output with default speed.
//! let mut pa1 = gpioa.pa1.into_push_pull_output(&mut gpioa.ctl0);
//! // Use API offered by `embedded-hal` to set `pa1` low,
//! // An LED light with cathode connected to PA1 should be lit now.
//! pa1.set_low().unwrap();
//! // We just end this program with infinite loop.
//! // A `wfi` instruction should be also acceptable here.
//! loop {}
//! }
//! ```
// #![deny(missing_docs)]
pub use gd32vf103_pac as pac;
/// Prelude
// == Notes on prelude trait function naming:
//
// If we wrap some register modules into one Rust `mod`, we infer that
// all the modules share common switches, clocks or unlock process.
//
// To take apart whole module into functional module register groups,
// we use traits with one function. Function name can be arbitrary in
// theory but we prefer following frequent function names:
// - split
// - constrain
// - configure
//
// The function name should depends on how the modules logically effect
// each other:
//
// If logical state of module registers do not depend on each other,
// the trait function name could be `split`.
//
// If logical states of module registers is under inherit or hierarchy
// relation thus may depend on each other, name could be `constain`
// or `configure`. If all combination of register states are valid,
// use `configure`; otherwise if some combinations are invalid, use
// `constrain`.