diff --git a/tm4c129x-hal/Cargo.toml b/tm4c129x-hal/Cargo.toml index 32e5aac..f06aacd 100644 --- a/tm4c129x-hal/Cargo.toml +++ b/tm4c129x-hal/Cargo.toml @@ -15,7 +15,7 @@ repository = "https://github.com/thejpster/tm4c-hal/tm4c129x-hal" edition = "2018" [dependencies] -bare-metal = "*" +bare-metal = "0.2.4" cortex-m = "0.5" nb = "0.1" tm4c129x = "0.7" @@ -33,7 +33,7 @@ version = "0.2" features = ["unproven"] [dependencies.smoltcp] -git = "https://github.com/m-labs/smoltcp" +version = "0.5.0" default_features = false features = [ "proto-ipv4", @@ -51,7 +51,7 @@ version = "1.0" default-features = false [dependencies.vcell] -version = "*" +version = "0.1.0" features = ["const-fn"] [features] diff --git a/tm4c129x-hal/src/edes_old.rs b/tm4c129x-hal/src/edes_old.rs index 6a21329..f1f975e 100644 --- a/tm4c129x-hal/src/edes_old.rs +++ b/tm4c129x-hal/src/edes_old.rs @@ -1,3 +1,5 @@ +#![allow(dead_code)] + pub const DES0_TX_CTRL_OWN: u32 = 2147483648; pub const DES0_TX_CTRL_INTERRUPT: u32 = 1073741824; pub const DES0_TX_CTRL_LAST_SEG: u32 = 536870912; diff --git a/tm4c129x-hal/src/ethernet.rs b/tm4c129x-hal/src/ethernet.rs index 056fa63..7b5bf32 100644 --- a/tm4c129x-hal/src/ethernet.rs +++ b/tm4c129x-hal/src/ethernet.rs @@ -62,9 +62,9 @@ impl EphyReg { } } -const NUM_TX_DESCRIPTORS: usize = 10; +const NUM_TX_DESCRIPTORS: usize = 1; const NUM_RX_DESCRIPTORS: usize = 10; -static RX_DESCRIPTORS: [RDES; NUM_TX_DESCRIPTORS] = [ +static RX_DESCRIPTORS: [RDES; NUM_RX_DESCRIPTORS] = [ RDES::new(), RDES::new(), RDES::new(), @@ -76,22 +76,14 @@ static RX_DESCRIPTORS: [RDES; NUM_TX_DESCRIPTORS] = [ RDES::new(), RDES::new(), ]; -static TX_DESCRIPTORS: [TDES; NUM_RX_DESCRIPTORS] = [ - TDES::new(), - TDES::new(), - TDES::new(), - TDES::new(), - TDES::new(), - TDES::new(), - TDES::new(), - TDES::new(), - TDES::new(), - TDES::new(), -]; +static TX_DESCRIPTORS: [TDES; NUM_TX_DESCRIPTORS] = [TDES::new()]; const RX_BUFFER_SIZE: usize = 1536; static mut RX_BUFFERS: [[u8; RX_BUFFER_SIZE]; NUM_RX_DESCRIPTORS] = [[0; RX_BUFFER_SIZE]; NUM_RX_DESCRIPTORS]; +const TX_BUFFER_SIZE: usize = RX_BUFFER_SIZE; +static mut TX_BUFFERS: [[u8; TX_BUFFER_SIZE]; NUM_TX_DESCRIPTORS] = + [[0; TX_BUFFER_SIZE]; NUM_TX_DESCRIPTORS]; fn emac_reset(emac0: &EMAC0) { emac0.dmabusmod.modify(|_, w| w.swr().set_bit()); @@ -137,29 +129,17 @@ fn emac_phy_config_set( fn emac_init( emac0: &EMAC0, - _sysclk: u32, + sysclk: u32, mut rx_burst: u32, mut tx_burst: u32, desc_skip_size: u32, ) { - // uint32_t ui32Val, ui32Div; - - // // - // // Parameter sanity checks. - // // - // ASSERT(ui32DescSkipSize < 32); + // Parameter sanity checks. assert!(desc_skip_size < 32); - // ASSERT(ui32TxBurst < (32 * 8)); assert!(tx_burst < 32 * 8); - // ASSERT(ui32RxBurst < (32 * 8)); assert!(rx_burst < 32 * 8); - // // - // // Make sure that the DMA software reset is clear before continuing. - // // - // while(HWREG(EMAC0_BASE + EMAC_O_DMABUSMOD) & EMAC_DMABUSMOD_SWR) - // { - // } + // Make sure that the DMA software reset is clear before continuing. while emac0.dmabusmod.read().swr().bit_is_set() {} emac0.dmabusmod.modify(|_, w| { @@ -167,7 +147,6 @@ fn emac_init( // descriptors so we need to OR in EMAC_DMABUSMOD_ATDS here. // Do we need to use the 8X burst length multiplier? - if tx_burst > 32 || rx_burst > 32 { // Divide both burst lengths by 8 and set the 8X burst length multiplier. w._8xpbl().set_bit(); @@ -201,28 +180,23 @@ fn emac_init( w }); - // // - // // Default the MII CSR clock divider based on the fastest system clock. - // // - // ui32Div = g_pi16MIIClockDiv[NUM_CLOCK_DIVISORS - 1].ui32Divisor; - - // // - // // Find the MII CSR clock divider to use based on the current system clock. - // // - // for(ui32Val = 0; ui32Val < NUM_CLOCK_DIVISORS; ui32Val++) - // { - // if(ui32SysClk <= g_pi16MIIClockDiv[ui32Val].ui32SysClockMax) - // { - // ui32Div = g_pi16MIIClockDiv[ui32Val].ui32Divisor; - // break; - // } - // } - - // // - // // Set the MII CSR clock speed. - // // - // HWREG(ui32Base + EMAC_O_MIIADDR) = ((HWREG(ui32Base + EMAC_O_MIIADDR) & - // ~EMAC_MIIADDR_CR_M) | ui32Div); + unsafe { + emac0.miiaddr.modify(|_, w| { + w.cr().bits(if sysclk < 20_000_000 { + panic!() + } else if sysclk < 35_000_000 { + 0x8 + } else if sysclk < 60_000_000 { + 0xc + } else if sysclk < 100_000_000 { + 0x0 + } else if sysclk < 150_000_000 { + 0x4 + } else { + panic!() + }) + }); + } // Disable all the MMC interrupts as these are enabled by default at reset. unsafe { @@ -268,6 +242,7 @@ pub struct EthernetDevice { tx_index: usize, rx_index: usize, emac0: EMAC0, + tx_descriptor_reserved: [bool; NUM_TX_DESCRIPTORS], } impl EthernetDevice { @@ -337,9 +312,20 @@ impl EthernetDevice { unsafe { for i in 0..NUM_TX_DESCRIPTORS { + TX_DESCRIPTORS[i].tdes0.write(|w| { + w.bits( + DES0_TX_CTRL_LAST_SEG + | DES0_TX_CTRL_FIRST_SEG + | DES0_TX_CTRL_CHAINED + | DES0_TX_CTRL_IP_ALL_CKHSUMS, + ) + }); TX_DESCRIPTORS[i] .tdes1 .write(|w| w.bits(DES1_TX_CTRL_SADDR_INSERT)); + TX_DESCRIPTORS[i] + .tdes2 + .write(|w| w.bits(&mut TX_BUFFERS[i] as *mut _ as *mut _ as u32)); TX_DESCRIPTORS[i].tdes3.write(|w| { w.bits(if i == NUM_TX_DESCRIPTORS - 1 { &TX_DESCRIPTORS[0] @@ -347,11 +333,9 @@ impl EthernetDevice { &TX_DESCRIPTORS[i + 1] } as *const _ as u32) }); - TX_DESCRIPTORS[i].tdes0.write(|w| w.bits(0)); } for i in 0..NUM_RX_DESCRIPTORS { - RX_DESCRIPTORS[i].rdes0.write(|w| w.bits(DES0_RX_CTRL_OWN)); RX_DESCRIPTORS[i].rdes1.write(|w| { w.bits( DES1_RX_CTRL_CHAINED @@ -368,6 +352,7 @@ impl EthernetDevice { &RX_DESCRIPTORS[i + 1] } as *const _ as u32) }); + RX_DESCRIPTORS[i].rdes0.write(|w| w.own().set_bit()); } emac0 @@ -392,6 +377,11 @@ impl EthernetDevice { // unsafe { // EMACIntClear(emac0_base, EMACIntStatus(emac0_base, false)); // } + unsafe { + emac0.dmaim.write(|w| w.bits(0xffff_ffff)); + emac0.ephyim.write(|w| w.bits(0xffff_ffff)); + } + emac_tx_enable(&emac0); emac_rx_enable(&emac0); nvic.enable(tm4c129x::Interrupt::EMAC0); @@ -400,6 +390,7 @@ impl EthernetDevice { rx_index: 0, tx_index: 0, emac0, + tx_descriptor_reserved: [false; NUM_TX_DESCRIPTORS], } } } @@ -410,39 +401,65 @@ impl<'a> Device<'a> for EthernetDevice { fn receive(&'a mut self) -> Option<(Self::RxToken, Self::TxToken)> { // Make sure that we own the receive descriptor. - unsafe { - if RX_DESCRIPTORS[self.rx_index].rdes0.read().bits() & DES0_RX_CTRL_OWN - == DES0_RX_CTRL_OWN - { - return None; - } + let rx_descriptor = &RX_DESCRIPTORS[self.rx_index]; + if rx_descriptor.rdes0.read().own().bit_is_set() { + return None; } - let result = Some(( - RxToken { - descriptor: &RX_DESCRIPTORS[self.rx_index], - }, - TxToken { - index: &mut self.tx_index, - emac0: &mut self.emac0, - }, - )); + let tx_reservation = &mut self.tx_descriptor_reserved[self.tx_index]; + if *tx_reservation { + return None; + } + let tx_descriptor = &TX_DESCRIPTORS[self.tx_index]; + if tx_descriptor.tdes0.read().own().bit_is_set() { + return None; + } + let tx_buffer = unsafe { &mut TX_BUFFERS[self.tx_index] }; self.rx_index += 1; if self.rx_index == NUM_RX_DESCRIPTORS { self.rx_index = 0; } + self.tx_index += 1; + if self.tx_index == NUM_TX_DESCRIPTORS { + self.tx_index = 0; + } - result + Some(( + RxToken { + descriptor: rx_descriptor, + }, + TxToken { + descriptor: tx_descriptor, + buffer: tx_buffer, + reservation: tx_reservation, + emac0: &self.emac0, + }, + )) } - fn transmit(&'a mut self) -> Option<(Self::TxToken)> { - let result = Some(TxToken { - index: &mut self.tx_index, - emac0: &mut self.emac0, - }); + fn transmit(&'a mut self) -> Option { + let tx_reservation = &mut self.tx_descriptor_reserved[self.tx_index]; + if *tx_reservation { + return None; + } + let tx_descriptor = &TX_DESCRIPTORS[self.tx_index]; + if tx_descriptor.tdes0.read().own().bit_is_set() { + return None; + } + let tx_buffer = unsafe { &mut TX_BUFFERS[self.tx_index] }; - result + self.tx_index += 1; + if self.tx_index == NUM_TX_DESCRIPTORS { + self.tx_index = 0; + } + + Some(TxToken { + descriptor: tx_descriptor, + buffer: tx_buffer, + reservation: tx_reservation, + emac0: &self.emac0, + }) } fn capabilities(&self) -> DeviceCapabilities { @@ -498,7 +515,7 @@ impl<'a> phy::RxToken for RxToken<'a> { } else { result = Err(smoltcp::Error::Checksum); } - self.descriptor.rdes0.write(|w| w.bits(DES0_RX_CTRL_OWN)); + self.descriptor.rdes0.write(|w| w.own().set_bit()); } result @@ -506,8 +523,16 @@ impl<'a> phy::RxToken for RxToken<'a> { } pub struct TxToken<'a> { - index: &'a mut usize, - emac0: &'a mut EMAC0, + descriptor: &'a TDES, + buffer: &'a mut [u8], + reservation: &'a mut bool, + emac0: &'a EMAC0, +} + +impl<'a> Drop for TxToken<'a> { + fn drop(&mut self) { + *self.reservation = false; + } } impl<'a> phy::TxToken for TxToken<'a> { @@ -515,43 +540,25 @@ impl<'a> phy::TxToken for TxToken<'a> { where F: FnOnce(&mut [u8]) -> smoltcp::Result, { - let descriptor = &TX_DESCRIPTORS[*self.index]; - *self.index += 1; - if *self.index == NUM_TX_DESCRIPTORS { - *self.index = 0; - } - - while descriptor.tdes0.read().bits() & DES0_TX_CTRL_OWN == DES0_TX_CTRL_OWN {} - - assert!(len <= RX_BUFFER_SIZE); + assert!(self.descriptor.tdes0.read().own().bit_is_clear()); - let mut data: [u8; RX_BUFFER_SIZE] = unsafe { core::mem::uninitialized() }; - let result = f(&mut data); + assert!(len <= self.buffer.len()); + let result = f(self.buffer); // Fill in the packet size and pointer, and tell the transmitter to start work. unsafe { - descriptor.tdes1.write(|w| w.bits(len as u32)); - descriptor - .tdes2 - .write(|w| w.bits(&mut data as *mut _ as *mut _ as u32)); - descriptor.tdes0.write(|w| { - w.bits( - DES0_TX_CTRL_LAST_SEG - | DES0_TX_CTRL_FIRST_SEG - | DES0_TX_CTRL_CHAINED - | DES0_TX_CTRL_OWN - | DES0_TX_CTRL_IP_ALL_CKHSUMS, - ) - }); + self.descriptor + .tdes1 + .write(|w| w.tbs1().bits(len.try_into().unwrap())); } + self.descriptor.tdes0.modify(|_, w| w.own().set_bit()); + *self.reservation = false; // Tell the DMA to reacquire the descriptor now that we've filled it in. This // call is benign if the transmitter hasn't stalled and checking the state takes // longer than just issuing a poll demand so we do this for all packets. self.emac0.txpolld.write(|w| w); - while descriptor.tdes0.read().bits() & DES0_TX_CTRL_OWN == DES0_TX_CTRL_OWN {} - result } }