Skip to content

Commit d1e3188

Browse files
committed
feat: add w5500 driver
1 parent 228e57c commit d1e3188

File tree

7 files changed

+1021
-0
lines changed

7 files changed

+1021
-0
lines changed

examples/w5500/main.go

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package main
2+
3+
import (
4+
"machine"
5+
"net"
6+
"net/netip"
7+
"time"
8+
9+
"tinygo.org/x/drivers/netdev"
10+
"tinygo.org/x/drivers/w5500"
11+
)
12+
13+
func main() {
14+
machine.SPI0.Configure(machine.SPIConfig{
15+
Frequency: 33 * machine.MHz,
16+
})
17+
machine.GPIO17.Configure(machine.PinConfig{Mode: machine.PinOutput})
18+
19+
eth := w5500.New()
20+
eth.Configure(w5500.Config{
21+
SPI: machine.SPI0,
22+
CS: machine.GPIO17.Set,
23+
MAC: net.HardwareAddr{0xee, 0xbe, 0xe9, 0xa9, 0xb6, 0x4f},
24+
IP: netip.AddrFrom4([4]byte{192, 168, 1, 2}),
25+
SubnetMask: netip.AddrFrom4([4]byte{255, 255, 255, 0}),
26+
Gateway: netip.AddrFrom4([4]byte{192, 168, 1, 1}),
27+
})
28+
netdev.UseNetdev(eth)
29+
30+
for {
31+
if eth.LinkStatus() != w5500.LinkStatusUp {
32+
println("Waiting for link to be up")
33+
34+
time.Sleep(1 * time.Second)
35+
continue
36+
}
37+
break
38+
}
39+
}

smoketest.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,7 @@ tinygo build -size short -o ./build/test.hex -target=pico ./examples/tmc5160/mai
144144
tinygo build -size short -o ./build/test.uf2 -target=nicenano ./examples/sharpmem/main.go
145145
tinygo build -size short -o ./build/test.hex -target=feather-nrf52840 ./examples/max6675/main.go
146146
tinygo build -size short -o ./build/test.hex -target=pico ./examples/ens160/main.go
147+
tinygo build -size short -o ./build/test.hex -target=pico ./examples/w5500/main.go
147148
# network examples (espat)
148149
tinygo build -size short -o ./build/test.hex -target=challenger-rp2040 ./examples/net/ntpclient/
149150
# network examples (wifinina)

w5500/debug.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package w5500
2+
3+
type debug uint8
4+
5+
const (
6+
debugNetdev debug = 1 << iota // show netdev entry points
7+
debugDetail // show chatty w5500 cmds
8+
9+
debugOff = 0
10+
debugAll = debugNetdev | debugDetail
11+
)
12+
13+
func debugging(want debug) bool {
14+
return (_debug & want) != 0
15+
}

w5500/io.go

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
package w5500
2+
3+
import (
4+
"fmt"
5+
"time"
6+
)
7+
8+
func (d *Device) irqPoll(sockn uint8, state uint8, deadline time.Time) uint8 {
9+
waitTime := 500 * time.Microsecond
10+
for {
11+
if !deadline.IsZero() && time.Now().After(deadline) {
12+
if debugging(debugDetail) {
13+
fmt.Println(time.Now(), deadline)
14+
fmt.Printf("[Socket %d] Polling for IRQ %08b timed out.\r\n", sockn, state)
15+
}
16+
17+
// If a deadline is set and it has passed, return 0.
18+
return sockIntUnknown
19+
}
20+
21+
irq := d.readByte(sockInt, sockAddr(sockn)) & 0b00011111
22+
if got := irq & state; got != 0 {
23+
// Acknowledge the interrupt.
24+
d.writeByte(sockInt, sockAddr(sockn), got)
25+
26+
if debugging(debugDetail) {
27+
fmt.Printf("[Socket %d] Got IRQ %08b\r\n", sockn, got)
28+
}
29+
30+
return got
31+
}
32+
33+
d.mu.Unlock()
34+
35+
time.Sleep(waitTime)
36+
37+
// Exponential backoff for polling.
38+
waitTime *= 2
39+
if waitTime > 10*time.Millisecond {
40+
waitTime = 10 * time.Millisecond
41+
}
42+
43+
d.mu.Lock()
44+
}
45+
}
46+
47+
func (d *Device) read(addr uint16, bsb uint8, p []byte) {
48+
d.cs(false)
49+
if len(p) == 0 {
50+
return
51+
}
52+
53+
d.sendReadHeader(addr, bsb)
54+
_ = d.bus.Tx(nil, p)
55+
d.cs(true)
56+
}
57+
58+
func (d *Device) readUint16(addr uint16, bsb uint8) uint16 {
59+
d.cs(false)
60+
d.sendReadHeader(addr, bsb)
61+
buf := d.cmdBuf
62+
_ = d.bus.Tx(nil, buf[:2])
63+
d.cs(true)
64+
return uint16(buf[1]) | uint16(buf[0])<<8
65+
}
66+
67+
func (d *Device) readByte(addr uint16, bsb uint8) byte {
68+
d.cs(false)
69+
d.sendReadHeader(addr, bsb)
70+
r, _ := d.bus.Transfer(byte(0))
71+
d.cs(true)
72+
return r
73+
}
74+
75+
func (d *Device) write(addr uint16, bsb uint8, p []byte) {
76+
d.cs(false)
77+
if len(p) == 0 {
78+
return
79+
}
80+
d.sendWriteHeader(addr, bsb)
81+
_ = d.bus.Tx(p, nil)
82+
d.cs(true)
83+
}
84+
85+
func (d *Device) writeUint16(addr uint16, bsb uint8, v uint16) {
86+
d.cs(false)
87+
d.sendWriteHeader(addr, bsb)
88+
buf := d.cmdBuf
89+
buf[0] = byte(v >> 8)
90+
buf[1] = byte(v & 0xff)
91+
_ = d.bus.Tx(buf[:2], nil)
92+
d.cs(true)
93+
}
94+
95+
func (d *Device) writeByte(addr uint16, bsb uint8, b byte) {
96+
d.cs(false)
97+
d.sendWriteHeader(addr, bsb)
98+
_, _ = d.bus.Transfer(b)
99+
d.cs(true)
100+
}
101+
102+
func (d *Device) sendReadHeader(addr uint16, bsb uint8) {
103+
buf := d.cmdBuf
104+
buf[0] = byte(addr >> 8)
105+
buf[1] = byte(addr & 0xff)
106+
buf[2] = bsb<<3 | 0b000
107+
_ = d.bus.Tx(buf, nil)
108+
}
109+
110+
func (d *Device) sendWriteHeader(addr uint16, bsb uint8) {
111+
buf := d.cmdBuf
112+
buf[0] = byte(addr >> 8)
113+
buf[1] = byte(addr & 0xff)
114+
buf[2] = bsb<<3 | 0b100
115+
_ = d.bus.Tx(buf, nil)
116+
}

0 commit comments

Comments
 (0)