1#![no_std]
2
3pub use musb::{MusbInstance, regs};
4
5#[derive(defmt::Format)]
7pub enum FifoSizing {
8 Static,
10 Dynamic,
12}
13
14#[derive(defmt::Format)]
16pub enum UtmiDataWidth {
17 Bit8,
19 Bit16,
21 Unknown(u8),
23}
24
25pub struct Configuration {
29 pub mprxe: bool,
31 pub mptxe: bool,
32 pub big_endian: bool,
33 pub hbrxe: bool,
34 pub hbtxe: bool,
35 pub dyn_fifo_sizing: FifoSizing,
36 pub soft_connect: bool,
37 pub utmi_data_width: UtmiDataWidth,
38
39 pub tx_fifo_sizes: [u16; 16],
41 pub rx_fifo_sizes: [u16; 16],
42
43 pub rx_endpoints: u8,
45 pub tx_endpoints: u8,
46 pub dma_channels: u8,
47 pub ram_bits: u8,
48 pub wtcon: u8,
49 pub wtid: u8,
50 pub vplen: u8,
51 pub hs_eof1: u8,
52 pub fs_eof1: u8,
53 pub ls_eof1: u8,
54
55 epinfo_is_zero: bool,
57 raminfo_is_zero: bool,
58 linkinfo_is_zero: bool,
59 vplen_is_zero: bool,
60 hs_eof1_is_zero: bool,
61 fs_eof1_is_zero: bool,
62 ls_eof1_is_zero: bool,
63}
64
65impl Configuration {
66 pub fn read<T: MusbInstance>() -> Self {
71 let regs = T::regs();
72
73 defmt::trace!("INDEX addr: 0x{:X}", ®s.index().as_ptr());
74 regs.index().write(|w| w.set_index(0));
76 let configdata = regs.configdata().read();
77 let mprxe = configdata.mprxe();
78 let mptxe = configdata.mptxe();
79 let big_endian = configdata.big_endian();
80 let hbrxe = configdata.hbrxe();
81 let hbtxe = configdata.hbtxe();
82 let dyn_fifo_sizing = if configdata.dyn_fifo_sizing() {
83 FifoSizing::Dynamic
84 } else {
85 FifoSizing::Static
86 };
87 let soft_connect = configdata.soft_con_e();
88 let utmi_data_width = match configdata.utmi_data_width().into() {
89 0 => UtmiDataWidth::Bit8,
90 1 => UtmiDataWidth::Bit16,
91 val => UtmiDataWidth::Unknown(val),
92 };
93
94 let mut tx_fifo_sizes = [0u16; 16];
96 let mut rx_fifo_sizes = [0u16; 16];
97
98 if let FifoSizing::Static = dyn_fifo_sizing {
99 for i in 0..=15 {
100 regs.index().write(|w| w.set_index(i));
101 let tx_nibble = regs.fifosize().read().tx_fifo_size();
102 let rx_nibble = regs.fifosize().read().rx_fifo_size();
103 tx_fifo_sizes[i as usize] = Self::decode_fifo_size_nibble(tx_nibble);
106
107 if rx_nibble == 0xF {
108 rx_fifo_sizes[i as usize] = u16::MAX;
110 } else {
111 rx_fifo_sizes[i as usize] = Self::decode_fifo_size_nibble(rx_nibble);
112 }
113 }
114 }
115 regs.index().write(|w| w.set_index(0));
116
117 let epinfo_reader = regs.epinfo().read();
121 let epinfo_is_zero = epinfo_reader.0 == 0;
122 let rx_endpoints = epinfo_reader.rx_end_points();
123 let tx_endpoints = epinfo_reader.tx_end_points();
124
125 let raminfo_reader = regs.raminfo().read();
127 let raminfo_is_zero = raminfo_reader.0 == 0;
128 let dma_channels = raminfo_reader.dmachans();
129 let ram_bits = raminfo_reader.ram_bits();
130
131 let linkinfo_reader = regs.linkinfo().read();
133 let linkinfo_is_zero = linkinfo_reader.0 == 0;
134 let wtcon = linkinfo_reader.wtcon();
135 let wtid = linkinfo_reader.wtid();
136
137 let vplen_reader = regs.vplen().read();
139 let vplen_is_zero = vplen_reader.0 == 0;
140 let vplen = vplen_reader.vplen();
141
142 let hs_eof1_reader = regs.hs_eof1().read();
144 let hs_eof1_is_zero = hs_eof1_reader.0 == 0;
145 let hs_eof1 = hs_eof1_reader.hs_eof1();
146
147 let fs_eof1_reader = regs.fs_eof1().read();
149 let fs_eof1_is_zero = fs_eof1_reader.0 == 0;
150 let fs_eof1 = fs_eof1_reader.fs_eof1();
151
152 let ls_eof1_reader = regs.ls_eof1().read();
154 let ls_eof1_is_zero = ls_eof1_reader.0 == 0;
155 let ls_eof1 = ls_eof1_reader.ls_eof1();
156
157 Self {
158 mprxe, mptxe, big_endian, hbrxe, hbtxe, dyn_fifo_sizing,
159 tx_fifo_sizes, rx_fifo_sizes,
160 soft_connect, utmi_data_width,
161 rx_endpoints, tx_endpoints, dma_channels, ram_bits,
162 wtcon, wtid, vplen, hs_eof1, fs_eof1, ls_eof1,
163 epinfo_is_zero, raminfo_is_zero, linkinfo_is_zero,
164 vplen_is_zero, hs_eof1_is_zero, fs_eof1_is_zero, ls_eof1_is_zero,
165 }
166 }
167
168 fn decode_fifo_size_nibble(nibble: u8) -> u16 {
172 match nibble {
173 3..=13 => 1u16 << nibble,
174 _ => 0, }
176 }
177
178 pub fn print_defmt(&self) {
180 defmt::info!("--- MUSB Core Configuration ---");
181
182 defmt::info!("Core Configuration (from CONFIGDATA):");
184 defmt::info!(" - Automatic Bulk Packet Amalgamation (MPRxE): {}", self.mprxe);
185 defmt::info!(" - Automatic Bulk Packet Splitting (MPTxE): {}", self.mptxe);
186 if self.big_endian {
188 defmt::warn!(" - Endianness: Big Endian. (Documentation states this should be Little Endian)");
189 } else {
190 defmt::info!(" - Endianness: Little Endian");
191 }
192 defmt::info!(" - High-Bandwidth Rx ISO Endpoint Support (HBRxE): {}", self.hbrxe);
193 defmt::info!(" - High-Bandwidth Tx ISO Endpoint Support (HBTxE): {}", self.hbtxe);
194 defmt::info!(" - FIFO Sizing: {}", self.dyn_fifo_sizing);
195 if self.soft_connect {
196 defmt::info!(" - Connection Type: Soft Connect/Disconnect");
197 } else {
198 defmt::warn!(" - Connection Type: Hard-wired. (Documentation states this should be Soft Connect)");
199 }
200 defmt::info!(" - UTMI+ Data Width: {}", self.utmi_data_width);
201
202 defmt::info!("Endpoint FIFO Configuration (from FIFOSIZE):");
204 match self.dyn_fifo_sizing {
205 FifoSizing::Dynamic => {
206 defmt::info!(" - Dynamic FIFO Sizing is enabled. The FIFOSIZE register is not applicable.");
207 }
208 FifoSizing::Static => {
209 let mut found_any = false;
210 for i in 1..=15 {
211 let tx_size = self.tx_fifo_sizes[i];
212 let rx_size = self.rx_fifo_sizes[i];
213
214 if tx_size > 0 || rx_size > 0 {
215 found_any = true;
216 if tx_size > 0 {
217 if rx_size == u16::MAX {
218 defmt::info!(" - Endpoint {}: TX FIFO = {=u16} bytes, RX FIFO = (Shared with TX)", i, tx_size);
219 } else if rx_size > 0 {
220 defmt::info!(" - Endpoint {}: TX FIFO = {=u16} bytes, RX FIFO = {=u16} bytes", i, tx_size, rx_size);
221 } else {
222 defmt::info!(" - Endpoint {}: TX FIFO = {=u16} bytes, RX FIFO = (Not configured)", i, tx_size);
223 }
224 } else {
225 defmt::info!(" - Endpoint {}: TX FIFO = (Not configured), RX FIFO = {=u16} bytes", i, rx_size);
227 }
228 }
229 }
230 if !found_any {
231 defmt::warn!(" - No configured static FIFOs found for endpoints 1-15.");
232 }
233 }
234 }
235
236 defmt::info!("Endpoint Configuration (from EPINFO):");
238 if self.epinfo_is_zero {
239 defmt::warn!(" - The EPINFO register returned all zeros. It may be unimplemented or masked by the vendor.");
240 }
241 defmt::info!(" - Implemented TX Endpoints: {}", self.tx_endpoints);
242 defmt::info!(" - Implemented RX Endpoints: {}", self.rx_endpoints);
243
244 defmt::info!("RAM and DMA Configuration (from RAMINFO):");
246 if self.raminfo_is_zero {
247 defmt::warn!(" - The RAMINFO register returned all zeros. It may be unimplemented or masked by the vendor.");
248 }
249 defmt::info!(" - Implemented DMA Channels: {}", self.dma_channels);
250 defmt::info!(" - RAM Address Bus Width: {} bits", self.ram_bits);
251
252
253 defmt::info!("Timing and Delay Configuration (from LINKINFO):");
255 if self.linkinfo_is_zero {
256 defmt::warn!(" - The LINKINFO register returned all zeros. It may be unimplemented or masked by the vendor.");
258 }
259 let wtcon_us = (self.wtcon as f32) * 0.5333;
260 let wtid_ms = (self.wtid as f32) * 4.369;
261 defmt::info!(" - Connection Wait Time (WTCON): {} (~{=f32} us)", self.wtcon, wtcon_us);
262 defmt::info!(" - ID Reading Wait Time (WTID): {} (~{=f32} ms)", self.wtid, wtid_ms);
263
264 defmt::info!("VBUS Pulsing Charge Duration (VPLEN):");
266 if self.vplen_is_zero {
267 defmt::warn!(" - The VPLEN register returned all zeros. It may be unimplemented or masked by the vendor.");
269 }
270 let vplen_ms = (self.vplen as f32) * 0.5461;
271 defmt::info!(" - Value: {} (~{=f32} ms)", self.vplen, vplen_ms);
272
273
274 defmt::info!("End-of-Frame (EOF) Gap Configuration:");
276 if self.hs_eof1_is_zero { defmt::warn!(" - High-Speed (HS_EOF1): Register returned all zeros. May be unimplemented or masked.");
278 }
279 let hs_eof1_us = (self.hs_eof1 as f32) * 0.1333;
280 defmt::info!(" - High-Speed (HS_EOF1): {} (~{=f32} us)", self.hs_eof1, hs_eof1_us);
281
282 if self.fs_eof1_is_zero { defmt::warn!(" - Full-Speed (FS_EOF1): Register returned all zeros. May be unimplemented or masked.");
284 }
285 let fs_eof1_us = (self.fs_eof1 as f32) * 0.5333;
286 defmt::info!(" - Full-Speed (FS_EOF1): {} (~{=f32} us)", self.fs_eof1, fs_eof1_us);
287
288 if self.ls_eof1_is_zero { defmt::warn!(" - Low-Speed (LS_EOF1): Register returned all zeros. May be unimplemented or masked.");
290 }
291 let ls_eof1_us = (self.ls_eof1 as f32) * 1.067;
292 defmt::info!(" - Low-Speed (LS_EOF1): {} (~{=f32} us)", self.ls_eof1, ls_eof1_us);
293
294
295 defmt::info!("--- End of Configuration ---");
296 }
297}