aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2022-07-11 00:25:35 +0200
committerDario Nieuwenhuis <[email protected]>2022-07-11 00:25:35 +0200
commit069a57fcf85c725d000e03163716edb4ae3922ca (patch)
treee0b672124cdfc0c8d4a58896d887496f5dec7d1d /src
parente560415fde967483573d42f628e52501768584e0 (diff)
async ioctls working.
Diffstat (limited to 'src')
-rw-r--r--src/lib.rs192
-rw-r--r--src/structs.rs71
2 files changed, 175 insertions, 88 deletions
diff --git a/src/lib.rs b/src/lib.rs
index 5caf19267..3609ecaeb 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,16 +1,20 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait, concat_bytes)] 3#![feature(type_alias_impl_trait, concat_bytes, const_slice_from_raw_parts)]
4
5// This mod MUST go first, so that the others see its macros. 4// This mod MUST go first, so that the others see its macros.
6pub(crate) mod fmt; 5pub(crate) mod fmt;
7 6
7mod structs;
8
9use core::cell::Cell;
8use core::slice; 10use core::slice;
9 11
10use embassy::time::{block_for, Duration, Timer}; 12use embassy::time::{block_for, Duration, Timer};
11use embassy::util::yield_now; 13use embassy::util::yield_now;
12use embassy_rp::gpio::{Flex, Output, Pin}; 14use embassy_rp::gpio::{Flex, Output, Pin};
13 15
16use self::structs::*;
17
14fn swap16(x: u32) -> u32 { 18fn swap16(x: u32) -> u32 {
15 (x & 0xFF00FF00) >> 8 | (x & 0x00FF00FF) << 8 19 (x & 0xFF00FF00) >> 8 | (x & 0x00FF00FF) << 8
16} 20}
@@ -169,68 +173,73 @@ const CHIP: Chip = Chip {
169}; 173};
170 174
171#[derive(Clone, Copy)] 175#[derive(Clone, Copy)]
172#[repr(C)] 176enum IoctlState {
173struct SdpcmHeader { 177 Idle,
174 len: u16, 178
175 len_inv: u16, 179 Pending {
176 /// Rx/Tx sequence number 180 kind: u32,
177 sequence: u8, 181 cmd: u32,
178 /// 4 MSB Channel number, 4 LSB arbitrary flag 182 iface: u32,
179 channel_and_flags: u8, 183 buf: *const [u8],
180 /// Length of next data frame, reserved for Tx 184 },
181 next_length: u8, 185 Sent,
182 /// Data offset 186 Done,
183 header_length: u8,
184 /// Flow control bits, reserved for Tx
185 wireless_flow_control: u8,
186 /// Maximum Sequence number allowed by firmware for Tx
187 bus_data_credit: u8,
188 /// Reserved
189 reserved: [u8; 2],
190} 187}
191 188
192#[derive(Clone, Copy)] 189pub struct State {
193#[repr(C)] 190 ioctl_id: Cell<u16>,
194struct CdcHeader { 191 ioctl_state: Cell<IoctlState>,
195 cmd: u32,
196 out_len: u16,
197 in_len: u16,
198 flags: u16,
199 id: u16,
200 status: u32,
201} 192}
202 193
203#[derive(Clone, Copy)] 194impl State {
204#[repr(C)] 195 pub fn new() -> Self {
205struct BdcHeader { 196 Self {
206 flags: u8, 197 ioctl_id: Cell::new(0),
207 /// 802.1d Priority (low 3 bits) 198 ioctl_state: Cell::new(IoctlState::Idle),
208 priority: u8, 199 }
209 flags2: u8, 200 }
210 /// Offset from end of BDC header to packet data, in 4-uint8_t words. Leaves room for optional headers.
211 data_offset: u8,
212} 201}
213 202
214macro_rules! impl_bytes { 203pub struct Control<'a> {
215 ($t:ident) => { 204 state: &'a State,
216 impl $t { 205}
217 const SIZE: usize = core::mem::size_of::<Self>();
218 206
219 pub fn to_bytes(&self) -> [u8; Self::SIZE] { 207impl<'a> Control<'a> {
220 unsafe { core::mem::transmute(*self) } 208 pub async fn init(&mut self) {
221 } 209 let clm = unsafe { slice::from_raw_parts(0x10140000 as *const u8, 4752) };
222 210
223 pub fn from_bytes(bytes: &[u8; Self::SIZE]) -> Self { 211 let mut buf = [0; 8 + 12 + 1024];
224 unsafe { core::mem::transmute(*bytes) } 212 buf[0..8].copy_from_slice(b"clmload\x00");
225 } 213 buf[8..20].copy_from_slice(b"\x02\x10\x02\x00\x00\x04\x00\x00\x00\x00\x00\x00");
214 buf[20..].copy_from_slice(&clm[..1024]);
215 self.ioctl(2, 263, 0, &buf).await;
216 info!("IOCTL done");
217 }
218
219 async fn ioctl(&mut self, kind: u32, cmd: u32, iface: u32, buf: &[u8]) {
220 // TODO cancel ioctl on future drop.
221
222 while !matches!(self.state.ioctl_state.get(), IoctlState::Idle) {
223 yield_now().await;
226 } 224 }
227 }; 225
226 self.state.ioctl_id.set(self.state.ioctl_id.get().wrapping_add(1));
227
228 self.state
229 .ioctl_state
230 .set(IoctlState::Pending { kind, cmd, iface, buf });
231
232 while !matches!(self.state.ioctl_state.get(), IoctlState::Done) {
233 yield_now().await;
234 }
235
236 self.state.ioctl_state.set(IoctlState::Idle);
237 }
228} 238}
229impl_bytes!(SdpcmHeader);
230impl_bytes!(CdcHeader);
231impl_bytes!(BdcHeader);
232 239
233pub struct Driver<'a, PWR: Pin, CS: Pin, CLK: Pin, DIO: Pin> { 240pub struct Runner<'a, PWR: Pin, CS: Pin, CLK: Pin, DIO: Pin> {
241 state: &'a State,
242
234 pwr: Output<'a, PWR>, 243 pwr: Output<'a, PWR>,
235 244
236 /// SPI chip-select. 245 /// SPI chip-select.
@@ -249,18 +258,29 @@ pub struct Driver<'a, PWR: Pin, CS: Pin, CLK: Pin, DIO: Pin> {
249 backplane_window: u32, 258 backplane_window: u32,
250} 259}
251 260
252impl<'a, PWR: Pin, CS: Pin, CLK: Pin, DIO: Pin> Driver<'a, PWR, CS, CLK, DIO> { 261pub async fn new<'a, PWR: Pin, CS: Pin, CLK: Pin, DIO: Pin>(
253 pub fn new(pwr: Output<'a, PWR>, cs: Output<'a, CS>, clk: Output<'a, CLK>, dio: Flex<'a, DIO>) -> Self { 262 state: &'a State,
254 Self { 263 pwr: Output<'a, PWR>,
255 pwr, 264 cs: Output<'a, CS>,
256 cs, 265 clk: Output<'a, CLK>,
257 clk, 266 dio: Flex<'a, DIO>,
258 dio, 267) -> (Control<'a>, Runner<'a, PWR, CS, CLK, DIO>) {
259 backplane_window: 0xAAAA_AAAA, 268 let mut runner = Runner {
260 } 269 state,
261 } 270 pwr,
271 cs,
272 clk,
273 dio,
274 backplane_window: 0xAAAA_AAAA,
275 };
262 276
263 pub async fn init(&mut self) { 277 runner.init().await;
278
279 (Control { state }, runner)
280}
281
282impl<'a, PWR: Pin, CS: Pin, CLK: Pin, DIO: Pin> Runner<'a, PWR, CS, CLK, DIO> {
283 async fn init(&mut self) {
264 // Set strap to select gSPI mode. 284 // Set strap to select gSPI mode.
265 self.dio.set_as_output(); 285 self.dio.set_as_output();
266 self.dio.set_low(); 286 self.dio.set_low();
@@ -306,6 +326,8 @@ impl<'a, PWR: Pin, CS: Pin, CLK: Pin, DIO: Pin> Driver<'a, PWR, CS, CLK, DIO> {
306 self.bp_write32(CHIP.socsram_base_address + 0x10, 3); 326 self.bp_write32(CHIP.socsram_base_address + 0x10, 3);
307 self.bp_write32(CHIP.socsram_base_address + 0x44, 0); 327 self.bp_write32(CHIP.socsram_base_address + 0x44, 0);
308 328
329 let ram_addr = CHIP.atcm_ram_base_address;
330
309 // I'm flashing the firmwares independently at hardcoded addresses, instead of baking them 331 // I'm flashing the firmwares independently at hardcoded addresses, instead of baking them
310 // into the program with `include_bytes!` or similar, so that flashing the program stays fast. 332 // into the program with `include_bytes!` or similar, so that flashing the program stays fast.
311 // 333 //
@@ -314,9 +336,6 @@ impl<'a, PWR: Pin, CS: Pin, CLK: Pin, DIO: Pin> Driver<'a, PWR, CS, CLK, DIO> {
314 // probe-rs-cli download 43439A0.bin --format bin --chip RP2040 --base-address 0x10100000 336 // probe-rs-cli download 43439A0.bin --format bin --chip RP2040 --base-address 0x10100000
315 // probe-rs-cli download 43439A0.clm_blob --format bin --chip RP2040 --base-address 0x10140000 337 // probe-rs-cli download 43439A0.clm_blob --format bin --chip RP2040 --base-address 0x10140000
316 let fw = unsafe { slice::from_raw_parts(0x10100000 as *const u8, 224190) }; 338 let fw = unsafe { slice::from_raw_parts(0x10100000 as *const u8, 224190) };
317 let clm = unsafe { slice::from_raw_parts(0x10140000 as *const u8, 4752) };
318
319 let ram_addr = CHIP.atcm_ram_base_address;
320 339
321 info!("loading fw"); 340 info!("loading fw");
322 self.bp_write(ram_addr, fw); 341 self.bp_write(ram_addr, fw);
@@ -374,17 +393,20 @@ impl<'a, PWR: Pin, CS: Pin, CLK: Pin, DIO: Pin> Driver<'a, PWR, CS, CLK, DIO> {
374 let _ = self.read8(FUNC_BACKPLANE, REG_BACKPLANE_PULL_UP); 393 let _ = self.read8(FUNC_BACKPLANE, REG_BACKPLANE_PULL_UP);
375 */ 394 */
376 395
377 let mut buf = [0; 8 + 12 + 1024];
378 buf[0..8].copy_from_slice(b"clmload\x00");
379 buf[8..20].copy_from_slice(b"\x02\x10\x02\x00\x00\x04\x00\x00\x00\x00\x00\x00");
380 buf[20..].copy_from_slice(&clm[..1024]);
381 self.send_ioctl(2, 263, 0, &buf);
382
383 info!("init done "); 396 info!("init done ");
397 }
384 398
399 pub async fn run(mut self) -> ! {
385 let mut old_irq = 0; 400 let mut old_irq = 0;
386 let mut buf = [0; 2048]; 401 let mut buf = [0; 2048];
387 loop { 402 loop {
403 // Send stuff
404 if let IoctlState::Pending { kind, cmd, iface, buf } = self.state.ioctl_state.get() {
405 self.send_ioctl(kind, cmd, iface, unsafe { &*buf }, self.state.ioctl_id.get());
406 self.state.ioctl_state.set(IoctlState::Sent);
407 }
408
409 // Receive stuff
388 let irq = self.read16(FUNC_BUS, REG_BUS_INTERRUPT); 410 let irq = self.read16(FUNC_BUS, REG_BUS_INTERRUPT);
389 if irq != old_irq { 411 if irq != old_irq {
390 info!("irq: {:04x}", irq); 412 info!("irq: {:04x}", irq);
@@ -419,6 +441,7 @@ impl<'a, PWR: Pin, CS: Pin, CLK: Pin, DIO: Pin> Driver<'a, PWR, CS, CLK, DIO> {
419 } 441 }
420 } 442 }
421 443
444 // TODO use IRQs
422 yield_now().await; 445 yield_now().await;
423 } 446 }
424 } 447 }
@@ -453,14 +476,16 @@ impl<'a, PWR: Pin, CS: Pin, CLK: Pin, DIO: Pin> Driver<'a, PWR, CS, CLK, DIO> {
453 let cdc_header = 476 let cdc_header =
454 CdcHeader::from_bytes(packet[SdpcmHeader::SIZE..][..CdcHeader::SIZE].try_into().unwrap()); 477 CdcHeader::from_bytes(packet[SdpcmHeader::SIZE..][..CdcHeader::SIZE].try_into().unwrap());
455 478
456 // TODO check cdc_header.id matches 479 if cdc_header.id == self.state.ioctl_id.get() {
457 // TODO check status 480 assert_eq!(cdc_header.status, 0); // todo propagate error
481 self.state.ioctl_state.set(IoctlState::Done);
482 }
458 } 483 }
459 _ => {} 484 _ => {}
460 } 485 }
461 } 486 }
462 487
463 fn send_ioctl(&mut self, kind: u32, cmd: u32, iface: u32, data: &[u8]) { 488 fn send_ioctl(&mut self, kind: u32, cmd: u32, iface: u32, data: &[u8], id: u16) {
464 let mut buf = [0; 2048]; 489 let mut buf = [0; 2048];
465 490
466 let total_len = SdpcmHeader::SIZE + CdcHeader::SIZE + data.len(); 491 let total_len = SdpcmHeader::SIZE + CdcHeader::SIZE + data.len();
@@ -469,7 +494,7 @@ impl<'a, PWR: Pin, CS: Pin, CLK: Pin, DIO: Pin> Driver<'a, PWR, CS, CLK, DIO> {
469 len: total_len as u16, 494 len: total_len as u16,
470 len_inv: !total_len as u16, 495 len_inv: !total_len as u16,
471 sequence: 0x02, // todo 496 sequence: 0x02, // todo
472 channel_and_flags: 0, // control channle 497 channel_and_flags: 0, // control channel
473 next_length: 0, 498 next_length: 0,
474 header_length: SdpcmHeader::SIZE as _, 499 header_length: SdpcmHeader::SIZE as _,
475 wireless_flow_control: 0, 500 wireless_flow_control: 0,
@@ -482,7 +507,7 @@ impl<'a, PWR: Pin, CS: Pin, CLK: Pin, DIO: Pin> Driver<'a, PWR, CS, CLK, DIO> {
482 out_len: data.len() as _, 507 out_len: data.len() as _,
483 in_len: 0, 508 in_len: 0,
484 flags: kind as u16 | (iface as u16) << 12, 509 flags: kind as u16 | (iface as u16) << 12,
485 id: 1, // todo 510 id,
486 status: 0, 511 status: 0,
487 }; 512 };
488 513
@@ -780,16 +805,13 @@ impl<'a, PWR: Pin, CS: Pin, CLK: Pin, DIO: Pin> Driver<'a, PWR, CS, CLK, DIO> {
780 w |= 0x01; 805 w |= 0x01;
781 } 806 }
782 self.clk.set_high(); 807 self.clk.set_high();
783 delay();
784 808
785 // falling edge 809 // falling edge
786 self.clk.set_low(); 810 self.clk.set_low();
787 delay();
788 } 811 }
789 *word = w 812 *word = w
790 } 813 }
791 self.clk.set_low(); 814 self.clk.set_low();
792 delay();
793 } 815 }
794 816
795 fn spi_write(&mut self, words: &[u8]) { 817 fn spi_write(&mut self, words: &[u8]) {
@@ -804,25 +826,19 @@ impl<'a, PWR: Pin, CS: Pin, CLK: Pin, DIO: Pin> Driver<'a, PWR, CS, CLK, DIO> {
804 } else { 826 } else {
805 self.dio.set_high(); 827 self.dio.set_high();
806 } 828 }
807 delay();
808 829
809 // rising edge 830 // rising edge
810 self.clk.set_high(); 831 self.clk.set_high();
811 delay();
812 832
813 word = word << 1; 833 word = word << 1;
814 } 834 }
815 } 835 }
816 self.clk.set_low(); 836 self.clk.set_low();
817 delay(); 837
818 self.dio.set_as_input(); 838 self.dio.set_as_input();
819 } 839 }
820} 840}
821 841
822fn delay() {
823 //cortex_m::asm::delay(5);
824}
825
826macro_rules! nvram { 842macro_rules! nvram {
827 ($($s:literal,)*) => { 843 ($($s:literal,)*) => {
828 concat_bytes!($($s, b"\x00",)* b"\x00\x00") 844 concat_bytes!($($s, b"\x00",)* b"\x00\x00")
diff --git a/src/structs.rs b/src/structs.rs
new file mode 100644
index 000000000..fe5e89a37
--- /dev/null
+++ b/src/structs.rs
@@ -0,0 +1,71 @@
1#[derive(Clone, Copy)]
2#[repr(C)]
3pub struct SdpcmHeader {
4 pub len: u16,
5 pub len_inv: u16,
6 /// Rx/Tx sequence number
7 pub sequence: u8,
8 /// 4 MSB Channel number, 4 LSB arbitrary flag
9 pub channel_and_flags: u8,
10 /// Length of next data frame, reserved for Tx
11 pub next_length: u8,
12 /// Data offset
13 pub header_length: u8,
14 /// Flow control bits, reserved for Tx
15 pub wireless_flow_control: u8,
16 /// Maximum Sequence number allowed by firmware for Tx
17 pub bus_data_credit: u8,
18 /// Reserved
19 pub reserved: [u8; 2],
20}
21
22#[derive(Clone, Copy)]
23#[repr(C)]
24pub struct CdcHeader {
25 pub cmd: u32,
26 pub out_len: u16,
27 pub in_len: u16,
28 pub flags: u16,
29 pub id: u16,
30 pub status: u32,
31}
32
33#[derive(Clone, Copy)]
34#[repr(C)]
35pub struct BdcHeader {
36 pub flags: u8,
37 /// 802.1d Priority (low 3 bits)
38 pub priority: u8,
39 pub flags2: u8,
40 /// Offset from end of BDC header to packet data, in 4-uint8_t words. Leaves room for optional headers.
41 pub data_offset: u8,
42}
43
44#[derive(Clone, Copy)]
45#[repr(C)]
46pub struct DownloadHeader {
47 pub flag: u16,
48 pub dload_type: u16,
49 pub len: u32,
50 pub crc: u32,
51}
52
53macro_rules! impl_bytes {
54 ($t:ident) => {
55 impl $t {
56 pub const SIZE: usize = core::mem::size_of::<Self>();
57
58 pub fn to_bytes(&self) -> [u8; Self::SIZE] {
59 unsafe { core::mem::transmute(*self) }
60 }
61
62 pub fn from_bytes(bytes: &[u8; Self::SIZE]) -> Self {
63 unsafe { core::mem::transmute(*bytes) }
64 }
65 }
66 };
67}
68impl_bytes!(SdpcmHeader);
69impl_bytes!(CdcHeader);
70impl_bytes!(BdcHeader);
71impl_bytes!(DownloadHeader);