diff options
| -rw-r--r-- | .gdbinit | 23 | ||||
| -rw-r--r-- | .gitignore | 5 | ||||
| -rw-r--r-- | .gitmodules | 3 | ||||
| -rw-r--r-- | SConstruct | 11 | ||||
| m--------- | laks | 0 | ||||
| -rw-r--r-- | main.cpp | 160 | 
6 files changed, 202 insertions, 0 deletions
| diff --git a/.gdbinit b/.gdbinit new file mode 100644 index 0000000..2844d70 --- /dev/null +++ b/.gdbinit @@ -0,0 +1,23 @@ +define flash +file demo.elf +load +end + +define restart +run +end + +define attach_swd +mon swdp_scan +attach 1 +end + +define attach_jtag +mon jtag_scan +attach 1 +end + +file demo.elf +target extended-remote /dev/cu.usbmodem7FC181B1 + +set mem inaccessible-by-default off diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b137a4a --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +*.o +*.a +*.elf +*.swp +.sconsign.dblite diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..cd4f3c2 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "laks"] +	path = laks +	url = git://git.jvnv.net/laks.git diff --git a/SConstruct b/SConstruct new file mode 100644 index 0000000..ff0e6ce --- /dev/null +++ b/SConstruct @@ -0,0 +1,11 @@ +import os
 +
 +env = Environment(
 +	ENV = os.environ,
 +)
 +
 +SConscript('laks/build_rules')
 +
 +env.SelectMCU('stm32f407zg')
 +
 +env.Firmware('demo.elf', Glob('*.cpp'))
 diff --git a/laks b/laks new file mode 160000 +Subproject 234a69eb4f58a1b57e22656994adbd8f871bf7f diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..a18bb27 --- /dev/null +++ b/main.cpp @@ -0,0 +1,160 @@ +#include <rcc/rcc.h> +#include <rcc/syscfg.h> +#include <gpio/pin.h> +#include <os/time.h> +#include <net/ethernet.h> +#include <util/rblog.h> + +static Pin eth_pins[] = { +	// MDIO, MDC +	PA2, PC1, +	// REF_CLK, CRS, TX_EN +	PA1, PA7, PB11, +	// TXD0, TXD1, RXD0, RXD1 +	PB12, PB13, PC4, PC5 +}; + +RBLog<256, 2> eth_rblog; + +struct dmadesc_t { +	volatile uint32_t status; +	volatile uint32_t ctrl; +	volatile uint32_t buf; +	volatile uint32_t next; +}; + +dmadesc_t dmadesc[2]; +uint8_t eth_buf[2][2048]; + +class ETH_driver { +	private: +		ETH_t& eth; +		 +		dmadesc_t* dmadescp; +	 +	public: +		ETH_driver(ETH_t& e) : eth(e) {} +		 +		void enable() { +			// Reset MAC. +			ETH.dma_reg.BMR |= 1; +			while(ETH.dma_reg.BMR & 1); +			 +			dmadesc[0].status = (1 << 31); // OWN +			dmadesc[0].ctrl = (1 << 14) | 2048; // RCH +			dmadesc[0].buf = (uint32_t)eth_buf[0]; +			dmadesc[0].next = (uint32_t)&dmadesc[1]; +			 +			dmadesc[1].status = (1 << 31); // OWN +			dmadesc[1].ctrl = (1 << 14) | 2048; // RCH +			dmadesc[1].buf = (uint32_t)eth_buf[1]; +			dmadesc[1].next = (uint32_t)&dmadesc[0]; +			 +			dmadescp = &dmadesc[0]; +			 +			ETH.dma_reg.BMR = (1 << 16) | (16 << 8); +			ETH.dma_reg.RDLAR = (uint32_t)dmadesc; +			ETH.dma_reg.OMR = (1 << 1); // RXSTART +			 +			ETH.mac_reg.CR |= (1 << 14) | (1 << 11) | (1 << 2); +			ETH.mac_reg.FFR |= (1 << 31); +		} +		 +		uint16_t mdio_read(uint8_t phy, uint8_t reg) { +			eth.mac_reg.MIIAR = (phy << 11) | (reg << 6) | (4 << 2) | 1; +			 +			while(eth.mac_reg.MIIAR & 1); +			 +			eth_rblog.log("MDIO read: %#x = %#x", reg, eth.mac_reg.MIIDR); +			 +			return eth.mac_reg.MIIDR; +		} +		 +		void mdio_write(uint8_t phy, uint8_t reg, uint16_t data) { +			eth_rblog.log("MDIO write: %#x = %#x", reg, data); +			 +			eth.mac_reg.MIIDR = data; +			 +			eth.mac_reg.MIIAR = (phy << 11) | (reg << 6) | (4 << 2) | (1 << 1) | 1; +			 +			while(eth.mac_reg.MIIAR & 1); +		} +		 +		void process() { +			uint32_t lost_frames = ETH.dma_reg.MFBOCR; +			 +			if(lost_frames) { +				eth_rblog.log("Lost frames. MFBOCR = %#x", lost_frames); +			} +			 +			uint32_t status = dmadescp->status; +			 +			if(!(status & (1 << 31))) { +				eth_rblog.log("Got frame. status = %#x", status); +				 +				if(status & (1 << 9) && status & (1 << 8)) { +					uint32_t len = (status & 0x3fff0000) >> 16; +					 +					handle_ethernet((uint8_t*)dmadescp->buf, len); +				} +				 +				dmadescp->status = (1 << 31); // OWN +				dmadescp = (dmadesc_t*)dmadescp->next; +			} +		} +		 +		void handle_ethernet(uint8_t* buf, uint32_t len) { +			eth_rblog.log("Handling frame. len = %d", len); +			 +			if(len < 18) { +				eth_rblog.log("Invalid length, dropping."); +				return; +			} +			 +			uint16_t ethertype = (buf[12] << 8) | buf[13]; +			 +			eth_rblog.log("Ethertype: %#x", ethertype); +			 +			switch(ethertype) { +				case 0x8100: +					uint16_t vlan = (buf[14] << 8) | buf[15]; +					 +					eth_rblog.log("VLAN = %d", vlan); +					break; +			 +			} +		} +}; + +ETH_driver ethd(ETH); + +int main() { +	// Initialize system timer. +	STK.LOAD = 168000000 / 8 / 1000; // 1000 Hz. +	STK.CTRL = 0x03; +	 +	RCC.enable(RCC.GPIOA); +	RCC.enable(RCC.GPIOB); +	RCC.enable(RCC.GPIOC); +	 +	for(Pin& p : eth_pins) { +		p.set_mode(Pin::AF); +		p.set_af(11); +		p.set_speed(Pin::High); +	} +	 +	RCC.enable(RCC.SYSCFG); +	 +	// Select RMII mode. +	SYSCFG.PMC |= (1 << 23); +	 +	RCC.enable(RCC.ETHMAC); +	RCC.enable(RCC.ETHMACTX); +	RCC.enable(RCC.ETHMACRX); +	 +	ethd.enable(); +	 +	while(1) { +		ethd.process(); +	} +} | 
