Skip to content

Commit 5f19d6f

Browse files
committed
Correctly track DMA's current descriptor indexes
1 parent 2d38b43 commit 5f19d6f

File tree

1 file changed

+45
-34
lines changed

1 file changed

+45
-34
lines changed

tm4c129x-hal/src/ethernet.rs

Lines changed: 45 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use crate::edes_old::*;
44
use crate::sysctl;
55
use byteorder::ByteOrder;
66
use core::convert::TryInto;
7-
use smoltcp::phy::{self, Checksum, ChecksumCapabilities, Device, DeviceCapabilities};
7+
use smoltcp::phy::{self, ChecksumCapabilities, Device, DeviceCapabilities};
88
use smoltcp::time::Instant;
99
use tm4c129x::EMAC0;
1010

@@ -240,6 +240,8 @@ fn emac_rx_enable(emac0: &EMAC0) {
240240

241241
pub struct EthernetDevice {
242242
emac0: EMAC0,
243+
next_rx_descriptor: &'static RDES,
244+
next_tx_descriptor: &'static TDES,
243245
}
244246

245247
impl EthernetDevice {
@@ -333,6 +335,7 @@ impl EthernetDevice {
333335
}
334336

335337
for i in 0..NUM_RX_DESCRIPTORS {
338+
RX_DESCRIPTORS[i].rdes0.write(|w| w.own().set_bit());
336339
RX_DESCRIPTORS[i].rdes1.write(|w| {
337340
w.bits(
338341
DES1_RX_CTRL_CHAINED
@@ -349,7 +352,6 @@ impl EthernetDevice {
349352
&RX_DESCRIPTORS[i + 1]
350353
} as *const _ as u32)
351354
});
352-
RX_DESCRIPTORS[i].rdes0.write(|w| w.own().set_bit());
353355
}
354356

355357
emac0
@@ -380,7 +382,11 @@ impl EthernetDevice {
380382
emac_rx_enable(&emac0);
381383
nvic.enable(tm4c129x::Interrupt::EMAC0);
382384

383-
EthernetDevice { emac0 }
385+
EthernetDevice {
386+
emac0,
387+
next_rx_descriptor: &RX_DESCRIPTORS[0],
388+
next_tx_descriptor: &TX_DESCRIPTORS[0],
389+
}
384390
}
385391
}
386392

@@ -389,33 +395,33 @@ impl<'a> Device<'a> for EthernetDevice {
389395
type TxToken = TxToken<'a>;
390396

391397
fn receive(&'a mut self) -> Option<(Self::RxToken, Self::TxToken)> {
392-
let rx_descriptor = RX_DESCRIPTORS
393-
.iter()
394-
.find(|rxd| rxd.rdes0.read().own().bit_is_clear())?;
395-
396-
let tx_descriptor = TX_DESCRIPTORS
397-
.iter()
398-
.find(|txd| txd.tdes0.read().own().bit_is_clear())?;
398+
if self.next_rx_descriptor.rdes0.read().own().bit_is_set() {
399+
return None;
400+
}
401+
if self.next_tx_descriptor.tdes0.read().own().bit_is_set() {
402+
return None;
403+
}
399404

400405
Some((
401406
RxToken {
402-
descriptor: rx_descriptor,
407+
emac0: &self.emac0,
408+
descriptor_pointer: &mut self.next_rx_descriptor,
403409
},
404410
TxToken {
405411
emac0: &self.emac0,
406-
descriptor: tx_descriptor,
412+
descriptor_pointer: &mut self.next_tx_descriptor,
407413
},
408414
))
409415
}
410416

411417
fn transmit(&'a mut self) -> Option<Self::TxToken> {
412-
let tx_descriptor = TX_DESCRIPTORS
413-
.iter()
414-
.find(|txd| txd.tdes0.read().own().bit_is_clear())?;
418+
if self.next_tx_descriptor.tdes0.read().own().bit_is_set() {
419+
return None;
420+
}
415421

416422
Some(TxToken {
417423
emac0: &self.emac0,
418-
descriptor: tx_descriptor,
424+
descriptor_pointer: &mut self.next_tx_descriptor,
419425
})
420426
}
421427

@@ -438,69 +444,74 @@ impl<'a> Device<'a> for EthernetDevice {
438444
}
439445

440446
pub struct RxToken<'a> {
441-
descriptor: &'a RDES,
447+
emac0: &'a EMAC0,
448+
descriptor_pointer: &'a mut &'static RDES,
442449
}
443450

444451
impl<'a> phy::RxToken for RxToken<'a> {
445452
fn consume<R, F>(self, _timestamp: Instant, f: F) -> smoltcp::Result<R>
446453
where
447454
F: FnOnce(&[u8]) -> smoltcp::Result<R>,
448455
{
456+
let descriptor = *self.descriptor_pointer;
457+
449458
// We own the receive descriptor so check to see if it contains a valid frame.
450-
if self.descriptor.rdes0.read().bits() & DES0_RX_STAT_ERR == DES0_RX_STAT_ERR {
451-
self.descriptor.rdes0.write(|w| w.own().set_bit());
459+
if descriptor.rdes0.read().bits() & DES0_RX_STAT_ERR == DES0_RX_STAT_ERR {
460+
descriptor.rdes0.write(|w| w.own().set_bit());
452461
return Err(smoltcp::Error::Checksum);
453462
}
454463

455464
// We have a valid frame. First check that the "last descriptor" flag is set. We
456465
// sized the receive buffer such that it can always hold a valid frame so this
457466
// flag should never be clear at this point but...
458-
if self.descriptor.rdes0.read().bits() & DES0_RX_STAT_LAST_DESC != DES0_RX_STAT_LAST_DESC {
459-
self.descriptor.rdes0.write(|w| w.own().set_bit());
467+
if descriptor.rdes0.read().bits() & DES0_RX_STAT_LAST_DESC != DES0_RX_STAT_LAST_DESC {
468+
descriptor.rdes0.write(|w| w.own().set_bit());
460469
return Err(smoltcp::Error::Truncated);
461470
}
462471

463-
let len = ((self.descriptor.rdes0.read().bits() & DES0_RX_STAT_FRAME_LENGTH_M)
472+
let len = ((descriptor.rdes0.read().bits() & DES0_RX_STAT_FRAME_LENGTH_M)
464473
>> DES0_RX_STAT_FRAME_LENGTH_S) as usize;
465474
assert!(len <= RX_BUFFER_SIZE);
466-
let data = unsafe {
467-
core::slice::from_raw_parts(self.descriptor.rdes2.read().bits() as *mut u8, len)
468-
};
475+
let data =
476+
unsafe { core::slice::from_raw_parts(descriptor.rdes2.read().bits() as *mut u8, len) };
469477

470478
let result = f(data);
471-
self.descriptor.rdes0.write(|w| w.own().set_bit());
479+
480+
descriptor.rdes0.write(|w| w.own().set_bit());
481+
self.emac0.rxpolld.write(|w| w);
482+
*self.descriptor_pointer = unsafe { &*(descriptor.rdes3.read().bits() as *const _) };
472483
result
473484
}
474485
}
475486

476487
pub struct TxToken<'a> {
477488
emac0: &'a EMAC0,
478-
descriptor: &'a TDES,
489+
descriptor_pointer: &'a mut &'static TDES,
479490
}
480491

481492
impl<'a> phy::TxToken for TxToken<'a> {
482493
fn consume<R, F>(self, _timestamp: Instant, len: usize, f: F) -> smoltcp::Result<R>
483494
where
484495
F: FnOnce(&mut [u8]) -> smoltcp::Result<R>,
485496
{
497+
let descriptor = *self.descriptor_pointer;
498+
486499
assert!(len <= TX_BUFFER_SIZE);
500+
487501
let data = unsafe {
488-
core::slice::from_raw_parts_mut(self.descriptor.tdes2.read().bits() as *mut u8, len)
502+
core::slice::from_raw_parts_mut(descriptor.tdes2.read().bits() as *mut u8, len)
489503
};
490504
let result = f(data);
491505

492506
unsafe {
493-
self.descriptor
507+
descriptor
494508
.tdes1
495509
.write(|w| w.tbs1().bits(len.try_into().unwrap()));
496510
}
497-
self.descriptor.tdes0.modify(|_, w| w.own().set_bit());
498511

499-
// Tell the DMA to reacquire the descriptor now that we've filled it in. This
500-
// call is benign if the transmitter hasn't stalled and checking the state takes
501-
// longer than just issuing a poll demand so we do this for all packets.
512+
descriptor.tdes0.modify(|_, w| w.own().set_bit());
502513
self.emac0.txpolld.write(|w| w);
503-
514+
*self.descriptor_pointer = unsafe { &*(descriptor.tdes3.read().bits() as *const _) };
504515
result
505516
}
506517
}

0 commit comments

Comments
 (0)