diff --git a/.cargo/config b/.cargo/config new file mode 100644 index 0000000..5f0cd66 --- /dev/null +++ b/.cargo/config @@ -0,0 +1,12 @@ +[target.thumbv7em-none-eabihf] +runner = "gdb -q -x openocd.gdb" +rustflags = [ + "-C", "link-arg=-Tlink.x", +] + +[build] +# Pick ONE of these compilation targets +# target = "thumbv6m-none-eabi" # Cortex-M0 and Cortex-M0+ +# target = "thumbv7m-none-eabi" # Cortex-M3 +# target = "thumbv7em-none-eabi" # Cortex-M4 and Cortex-M7 (no FPU) +target = "thumbv7em-none-eabihf" # Cortex-M4F and Cortex-M7F (with FPU) \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index 6cf48df..a34ec7f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,5 +1,11 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +[[package]] +name = "aligned" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d39da9b88ae1a81c03c9c082b8db83f1d0e93914126041962af61034ab44c4a5" + [[package]] name = "aligned" version = "0.3.2" @@ -56,13 +62,25 @@ version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" +[[package]] +name = "cortex-m" +version = "0.5.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c0b159a1e8306949579de3698c841dba58058197b65c60807194e4fa1e7a554" +dependencies = [ + "aligned 0.2.0", + "bare-metal", + "cortex-m 0.6.2", + "volatile-register", +] + [[package]] name = "cortex-m" version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2954942fbbdd49996704e6f048ce57567c3e1a4e2dc59b41ae9fde06a01fc763" dependencies = [ - "aligned", + "aligned 0.3.2", "bare-metal", "volatile-register", ] @@ -102,8 +120,12 @@ dependencies = [ name = "enc424j600" version = "0.1.0" dependencies = [ - "aligned", + "aligned 0.3.2", + "cortex-m 0.5.10", + "cortex-m-rt", + "embedded-hal", "log", + "panic-itm", "smoltcp", "stm32f4xx-hal", "volatile-register", @@ -148,6 +170,15 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b1411551beb3c11dedfb0a90a0fa256b47d28b9ec2cdff34c25a2fa59e45dbdc" +[[package]] +name = "panic-itm" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98830d17a95587207e41edaa3009b143d326ce134b0e3538ac98246a67d66cc3" +dependencies = [ + "cortex-m 0.6.2", +] + [[package]] name = "proc-macro2" version = "1.0.18" @@ -227,7 +258,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "11460b4de3a84f072e2cf6e76306c64d27f405a0e83bace0a726f555ddf4bf33" dependencies = [ "bare-metal", - "cortex-m", + "cortex-m 0.6.2", "vcell", ] @@ -239,7 +270,7 @@ checksum = "b3a2f044469d1e3aff2cd02bee8b2724f3d5d91f3175e5d1ec99770320d16192" dependencies = [ "bare-metal", "cast", - "cortex-m", + "cortex-m 0.6.2", "cortex-m-rt", "embedded-hal", "nb", diff --git a/Cargo.toml b/Cargo.toml index c734370..a49d9c5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,6 +20,16 @@ smoltcp-phy = ["smoltcp"] stm32f407 = ["stm32f4xx-hal/stm32f407"] default = [] +[dev-dependencies] +cortex-m = "0.5" +cortex-m-rt = "0.6" +embedded-hal = "0.2" +panic-itm = "0.4" + +[[example]] +name = "tx_stm32f407" +required-features = ["stm32f407"] + [profile.release] codegen-units = 1 incremental = false diff --git a/README.md b/README.md index e89228d..e477ee7 100644 --- a/README.md +++ b/README.md @@ -1 +1,40 @@ # ENC424J600 Driver + +## Examples + +### Endless Pinging - `tx_stm32f407` + +This program demonstrates the Ethernet TX capability on an STM32F407 board connected to an ENC424J600 module via SPI. Once loaded and initialised, a specific ping packet is sent (broadcasted) every 100ms. Such a packet has the following properties: + +* Destination MAC Address: ff-ff-ff-ff-ff-ff +* Source MAC Address: 08-60-6e-44-42-95 +* Destination IP Address: 192.168.1.231 +* Source IP Address: 192.168.1.100 +* Frame Length in Bytes: 64 + +Note that this program uses ITM for logging output. + +#### How-to + +1. Prepare the Rust and Cargo environment for building and running the program on STM32F4xx Cortex-M platforms. + +2. Install [`itm`](https://docs.rs/itm/) on Cargo: + ``` + cargo install itm + ``` + If necessary, add your installation location (`~/.cargo/bin` by default) to `$PATH`. + +3. Connect your STM32F407 device to the computer. Without changing any code, you may use an STLink V2 debugger. + +4. Run OpenOCD with the appropriate configuration files (e.g. `interface/stlink-v2.cfg`, `target/stm32f4x.cfg`). + +5. With OpenOCD running, build and run this program: + ``` + cargo run --release --example=tx_stm32f407 --features=stm32f407 + ``` + Use appropriate GDB commands such as `c` for continuing. + +6. On a separate console window, monitor and observe the ITM output, which is located at the same directory as you started OpenOCD: + ``` + itmdump -f itm.log -F + ``` diff --git a/examples/tx_stm32f407.rs b/examples/tx_stm32f407.rs new file mode 100644 index 0000000..0589fc7 --- /dev/null +++ b/examples/tx_stm32f407.rs @@ -0,0 +1,129 @@ +#![no_std] +#![no_main] + +extern crate panic_itm; +use cortex_m::{iprint, iprintln}; + +use cortex_m_rt::entry; +use embedded_hal::watchdog::{WatchdogEnable, Watchdog}; +use embedded_hal::digital::v2::OutputPin; +use embedded_hal::blocking::delay::DelayMs; +use stm32f4xx_hal::{ + rcc::RccExt, + gpio::GpioExt, + watchdog::IndependentWatchdog, + time::U32Ext, + stm32::{CorePeripherals, Peripherals}, + delay::Delay, + spi::Spi +}; +use enc424j600; +use enc424j600::EthController; + +#[entry] +fn main() -> ! { + let mut cp = CorePeripherals::take().unwrap(); + cp.SCB.enable_icache(); + cp.SCB.enable_dcache(&mut cp.CPUID); + + let dp = Peripherals::take().unwrap(); + let clocks = dp.RCC.constrain() + .cfgr + .sysclk(168.mhz()) + .hclk(168.mhz()) + .pclk1(32.mhz()) + .pclk2(64.mhz()) + .freeze(); + let mut delay = Delay::new(cp.SYST, clocks); + + let mut itm = cp.ITM; + let stim0 = &mut itm.stim[0]; + + iprintln!(stim0, + "Eth TX Pinging on STM32-H407 via NIC100/ENC424J600"); + + // NIC100 / ENC424J600 Set-up + let spi1 = dp.SPI1; + let gpioa = dp.GPIOA.split(); + // Mapping: see Table 9, STM32F407ZG Manual + let spi1_sck = gpioa.pa5.into_alternate_af5(); + let spi1_miso = gpioa.pa6.into_alternate_af5(); + let spi1_mosi = gpioa.pa7.into_alternate_af5(); + let spi1_nss = gpioa.pa4.into_push_pull_output(); + // Map SPISEL: see Table 1, NIC100 Manual + let mut spisel = gpioa.pa1.into_push_pull_output(); + spisel.set_high().unwrap(); + delay.delay_ms(1_u32); + spisel.set_low().unwrap(); + // Create SPI1 for HAL + let spi_eth_port = Spi::spi1( + spi1, (spi1_sck, spi1_miso, spi1_mosi), + enc424j600::spi::SPI_MODE, enc424j600::spi::SPI_CLOCK.into(), + clocks); + let mut spi_eth = enc424j600::SpiEth::new(spi_eth_port, spi1_nss); + // Init + match spi_eth.init_dev() { + Ok(_) => { + iprintln!(stim0, "Ethernet initialised.") + } + Err(_) => { + panic!("Ethernet initialisation Failed!") + } + } + delay.delay_ms(1_u32); + iprintln!(stim0, + "- Delayed 1000us (>=256us), PHY regs are now available"); + + // Read MAC + let mut eth_mac_addr: [u8; 6] = [0; 6]; + spi_eth.read_from_mac(&mut eth_mac_addr); + iprintln!(stim0, + "MAC Address = {:02x}-{:02x}-{:02x}-{:02x}-{:02x}-{:02x}", + eth_mac_addr[5], eth_mac_addr[4], + eth_mac_addr[3], eth_mac_addr[2], + eth_mac_addr[1], eth_mac_addr[0]); + // Set to promiscuous mode + spi_eth.set_promiscuous(); + iprintln!(stim0, + "Promiscuous Mode ON"); + + // Init Rx/Tx buffers + spi_eth.init_rxbuf(); + spi_eth.init_txbuf(); + // Testing Eth TX + let eth_tx_dat: [u8; 64] = [ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x08, 0x60, + 0x6e, 0x44, 0x42, 0x95, 0x08, 0x06, 0x00, 0x01, + 0x08, 0x00, 0x06, 0x04, 0x00, 0x01, 0x08, 0x60, + 0x6e, 0x44, 0x42, 0x95, 0xc0, 0xa8, 0x01, 0x64, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xa8, + 0x01, 0xe7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x69, 0xd0, 0x85, 0x9f + ]; + loop { + let mut eth_tx_packet = enc424j600::tx::TxPacket::new(); + eth_tx_packet.update_frame(ð_tx_dat, 64); + iprintln!(stim0, + "Sending packet (len={:}): \ + dest={:02x}-{:02x}-{:02x}-{:02x}-{:02x}-{:02x} \ + src={:02x}-{:02x}-{:02x}-{:02x}-{:02x}-{:02x} \ + data={:02x}{:02x}{:02x}{:02x} {:02x}{:02x}{:02x}{:02x} ...", + eth_tx_packet.get_frame_length(), + eth_tx_packet.get_frame_byte(0), eth_tx_packet.get_frame_byte(1), eth_tx_packet.get_frame_byte(2), + eth_tx_packet.get_frame_byte(3), eth_tx_packet.get_frame_byte(4), eth_tx_packet.get_frame_byte(5), + eth_tx_packet.get_frame_byte(6), eth_tx_packet.get_frame_byte(7), eth_tx_packet.get_frame_byte(8), + eth_tx_packet.get_frame_byte(9), eth_tx_packet.get_frame_byte(10), eth_tx_packet.get_frame_byte(11), + eth_tx_packet.get_frame_byte(12), eth_tx_packet.get_frame_byte(13), + eth_tx_packet.get_frame_byte(14), eth_tx_packet.get_frame_byte(15), + eth_tx_packet.get_frame_byte(16), eth_tx_packet.get_frame_byte(17), + eth_tx_packet.get_frame_byte(18), eth_tx_packet.get_frame_byte(19) + ); + spi_eth.send_raw_packet(eth_tx_packet); + iprintln!(stim0, + "Packet sent"); + delay.delay_ms(100_u32); + } + + unreachable!() +} diff --git a/memory.x b/memory.x new file mode 100644 index 0000000..03fcd44 --- /dev/null +++ b/memory.x @@ -0,0 +1,10 @@ +MEMORY +{ + FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 2048K + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 112K + RAM2 (xrw) : ORIGIN = 0x2001C000, LENGTH = 16K + RAM3 (xrw) : ORIGIN = 0x20020000, LENGTH = 64K + CCMRAM (rw) : ORIGIN = 0x10000000, LENGTH = 64K +} + +_stack_start = ORIGIN(CCMRAM) + LENGTH(CCMRAM); diff --git a/openocd.gdb b/openocd.gdb new file mode 100644 index 0000000..9952bbf --- /dev/null +++ b/openocd.gdb @@ -0,0 +1,10 @@ +target remote :3333 + +# print demangled symbols by default +set print asm-demangle on + +monitor tpiu config internal itm.log uart off 168000000 +monitor itm port 0 on + +load +step