1use anyhow::Result;
6use std::time::Duration;
7
8use ot_hal::top::earlgrey::{PinmuxOutsel, PinmuxPeripheralIn};
9
10use crate::io::uart::Uart;
11use crate::test_utils::e2e_command::TestCommand;
12use crate::test_utils::rpc::{ConsoleRecv, ConsoleSend};
13use crate::test_utils::status::Status;
14
15include!(env!("gpio"));
17
18pub const GPIO_PINS: u32 = 32;
20
21pub static GPIO_INSTANCES: [(PinmuxPeripheralIn, PinmuxOutsel); 2] = [
23 (PinmuxPeripheralIn::Gpio0Gpio0, PinmuxOutsel::Gpio0Gpio0),
24 (PinmuxPeripheralIn::Gpio1Gpio0, PinmuxOutsel::Gpio1Gpio0),
25];
26
27pub fn peripheral_in(instance: u8, pin: u32) -> PinmuxPeripheralIn {
29 assert!(pin < GPIO_PINS, "GPIO pin {pin} out of range");
30 let (base, _) = GPIO_INSTANCES[usize::from(instance)];
31 PinmuxPeripheralIn(u32::from(base) + pin)
32}
33
34pub fn outsel(instance: u8, pin: u32) -> PinmuxOutsel {
36 assert!(pin < GPIO_PINS, "GPIO pin {pin} out of range");
37 let (_, base) = GPIO_INSTANCES[usize::from(instance)];
38 PinmuxOutsel(u32::from(base) + pin)
39}
40
41pub fn input_pin(input: PinmuxPeripheralIn) -> u32 {
43 GPIO_INSTANCES
44 .iter()
45 .map(|(base, _)| u32::from(input).wrapping_sub(u32::from(*base)))
46 .find(|i| *i < GPIO_PINS)
47 .expect("not a GPIO peripheral input")
48}
49
50pub fn output_pin(output: PinmuxOutsel) -> u32 {
52 GPIO_INSTANCES
53 .iter()
54 .map(|(_, base)| u32::from(output).wrapping_sub(u32::from(*base)))
55 .find(|i| *i < GPIO_PINS)
56 .expect("not a GPIO output select")
57}
58
59impl GpioSet {
60 fn execute(&self, uart: &dyn Uart) -> Result<()> {
61 TestCommand::GpioSet.send(uart)?;
62 self.send(uart)?;
63 Status::recv(uart, Duration::from_secs(300), false, false)?;
64 Ok(())
65 }
66
67 pub fn write(uart: &dyn Uart, instance: u8, pin: u32, state: bool) -> Result<()> {
68 let payload = GpioSet {
69 instance,
70 action: GpioAction::Write,
71 pin_mask: pin,
72 state: state.into(),
73 };
74 payload.execute(uart)
75 }
76 pub fn set_enabled(uart: &dyn Uart, instance: u8, pin: u32, state: bool) -> Result<()> {
77 let payload = GpioSet {
78 instance,
79 action: GpioAction::SetEnabled,
80 pin_mask: pin,
81 state: state.into(),
82 };
83 payload.execute(uart)
84 }
85
86 pub fn write_all(uart: &dyn Uart, instance: u8, state: u32) -> Result<()> {
87 let payload = GpioSet {
88 instance,
89 action: GpioAction::WriteAll,
90 pin_mask: 0,
91 state,
92 };
93 payload.execute(uart)
94 }
95 pub fn set_enabled_all(uart: &dyn Uart, instance: u8, state: u32) -> Result<()> {
96 let payload = GpioSet {
97 instance,
98 action: GpioAction::SetEnabledAll,
99 pin_mask: 0,
100 state,
101 };
102 payload.execute(uart)
103 }
104
105 pub fn write_masked(uart: &dyn Uart, instance: u8, mask: u32, state: u32) -> Result<()> {
106 let payload = GpioSet {
107 instance,
108 action: GpioAction::WriteMasked,
109 pin_mask: mask,
110 state,
111 };
112 payload.execute(uart)
113 }
114 pub fn set_enabled_masked(uart: &dyn Uart, instance: u8, mask: u32, state: u32) -> Result<()> {
115 let payload = GpioSet {
116 instance,
117 action: GpioAction::SetEnabledMasked,
118 pin_mask: mask,
119 state,
120 };
121 payload.execute(uart)
122 }
123 pub fn set_input_noise_filter(
124 uart: &dyn Uart,
125 instance: u8,
126 mask: u32,
127 state: u32,
128 ) -> Result<()> {
129 let payload = GpioSet {
130 instance,
131 action: GpioAction::SetInputNoiseFilter,
132 pin_mask: mask,
133 state,
134 };
135 payload.execute(uart)
136 }
137 pub fn irq_restore_all(uart: &dyn Uart, instance: u8, state: u32) -> Result<()> {
138 let payload = GpioSet {
139 instance,
140 action: GpioAction::IrqRestoreAll,
141 pin_mask: 0,
142 state,
143 };
144 payload.execute(uart)
145 }
146 pub fn irq_disable_all(uart: &dyn Uart, instance: u8, state: u32) -> Result<()> {
147 let payload = GpioSet {
148 instance,
149 action: GpioAction::IrqDisableAll,
150 pin_mask: 0,
151 state,
152 };
153 payload.execute(uart)
154 }
155 pub fn irq_acknowledge_all(uart: &dyn Uart, instance: u8) -> Result<()> {
156 let payload = GpioSet {
157 instance,
158 action: GpioAction::IrqAcknowledgeAll,
159 pin_mask: 0,
160 state: 0,
161 };
162 payload.execute(uart)
163 }
164 pub fn irq_set_trigger(
165 uart: &dyn Uart,
166 instance: u8,
167 state: u32,
168 trigger: String,
169 ) -> Result<()> {
170 match trigger.as_str() {
171 "rising" => {
172 let payload = GpioSet {
173 instance,
174 action: GpioAction::IrqSetTriggerRisingEdge,
175 pin_mask: 0,
176 state,
177 };
178 payload.execute(uart)
179 }
180 "falling" => {
181 let payload = GpioSet {
182 instance,
183 action: GpioAction::IrqSetTriggerFallingEdge,
184 pin_mask: 0,
185 state,
186 };
187 payload.execute(uart)
188 }
189 "high" => {
190 let payload = GpioSet {
191 instance,
192 action: GpioAction::IrqSetTriggerHigh,
193 pin_mask: 0,
194 state,
195 };
196 payload.execute(uart)
197 }
198 "low" => {
199 let payload = GpioSet {
200 instance,
201 action: GpioAction::IrqSetTriggerLow,
202 pin_mask: 0,
203 state,
204 };
205 payload.execute(uart)
206 }
207 _ => {
208 log::error!("unsupport trigger: {:?}", trigger);
209 Ok(())
210 }
211 }
212 }
213}
214
215impl GpioGet {
216 pub fn read_all(uart: &dyn Uart, instance: u8) -> Result<u32> {
217 TestCommand::GpioGet.send(uart)?;
218 GpioGetRequest { instance }.send(uart)?;
219 let data = GpioGet::recv(uart, Duration::from_secs(300), false, false)?;
220 Ok(data.state)
221 }
222}