Skip to content

Commit 9bbbc80

Browse files
author
BiffoBear
committed
Merged in updates from main.
2 parents aa30f2e + 81a9c69 commit 9bbbc80

File tree

2 files changed

+127
-36
lines changed

2 files changed

+127
-36
lines changed

adafruit_wiznet5k/adafruit_wiznet5k.py

Lines changed: 70 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -45,12 +45,13 @@
4545

4646
from random import randint
4747
import time
48+
import gc
4849
from micropython import const
4950

5051
from adafruit_bus_device.spi_device import SPIDevice
51-
from adafruit_wiznet5k.adafruit_wiznet5k_debug import debug_msg
5252
import adafruit_wiznet5k.adafruit_wiznet5k_dhcp as dhcp
5353
import adafruit_wiznet5k.adafruit_wiznet5k_dns as dns
54+
from adafruit_wiznet5k.adafruit_wiznet5k_debug import debug_msg
5455

5556
# Wiznet5k Registers
5657
_REG_MR = const(0x0000) # Mode
@@ -110,9 +111,9 @@
110111

111112
# Socket n Interrupt Register
112113
_SNIR_SEND_OK = const(0x10)
113-
_SNIR_TIMEOUT = const(0x08)
114+
SNIR_TIMEOUT = const(0x08)
114115
_SNIR_RECV = const(0x04)
115-
_SNIR_DISCON = const(0x02)
116+
SNIR_DISCON = const(0x02)
116117
_SNIR_CON = const(0x01)
117118

118119
_CH_SIZE = const(0x100)
@@ -149,6 +150,8 @@ class WIZNET5K: # pylint: disable=too-many-public-methods, too-many-instance-at
149150
_UDP_MODE = const(0x02)
150151
_TLS_MODE = const(0x03) # This is NOT currently implemented
151152

153+
_sockets_reserved = []
154+
152155
# pylint: disable=too-many-arguments
153156
def __init__(
154157
self,
@@ -192,6 +195,13 @@ def __init__(
192195
self._ch_base_msb = 0
193196
if self._w5xxx_init() != 1:
194197
raise RuntimeError("Failed to initialize WIZnet module.")
198+
if self._chip_type == "w5100s":
199+
WIZNET5K._sockets_reserved = [False] * (_W5100_MAX_SOCK_NUM - 1)
200+
elif self._chip_type == "w5500":
201+
WIZNET5K._sockets_reserved = [False] * (_W5200_W5500_MAX_SOCK_NUM - 1)
202+
else:
203+
raise RuntimeError("Unrecognized chip type.")
204+
195205
# Set MAC address
196206
self.mac_address = mac
197207
self.src_port = 0
@@ -719,23 +729,61 @@ def _send_socket_cmd(self, socket: int, cmd: int) -> None:
719729
while self.read_sncr(socket) != b"\x00":
720730
debug_msg("waiting for SNCR to clear...", self._debug)
721731

722-
def get_socket(self) -> int:
723-
"""Request, allocate and return a socket from the W5k chip.
732+
def get_socket(self, *, reserve_socket=False) -> int:
733+
"""
734+
Request, allocate and return a socket from the W5k chip.
735+
736+
Cycle through the sockets to find the first available one. If the called with
737+
reserve_socket=True, update the list of reserved sockets (intended to be used with
738+
socket.socket()). Note that reserved sockets must be released by calling
739+
cancel_reservation() once they are no longer needed.
740+
741+
If all sockets are reserved, no sockets are available for DNS calls, etc. Therefore,
742+
one socket cannot be reserved. Since socket 0 is the only socket that is capable of
743+
operating in MacRAW mode, it is the non-reservable socket.
724744
725-
Cycle through the sockets to find the first available one, if any.
745+
:param bool reserve_socket: Whether to reserve the socket.
726746
727-
:return int: The first available socket. Returns 0xFF if no sockets are free.
747+
:returns int: The first available socket.
748+
749+
:raises RuntimeError: If no socket is available.
728750
"""
729-
debug_msg("get_socket", self._debug)
751+
debug_msg("*** Get socket.", self._debug)
752+
# Prefer socket zero for none reserved calls as it cannot be reserved.
753+
if not reserve_socket and self.socket_status(0)[0] == SNSR_SOCK_CLOSED:
754+
debug_msg("Allocated socket # 0", self._debug)
755+
return 0
756+
# Then check the other sockets.
730757

731-
sock = _SOCKET_INVALID
732-
for _sock in range(self.max_sockets):
733-
status = self.socket_status(_sock)[0]
734-
if status == SNSR_SOCK_CLOSED:
735-
sock = _sock
736-
break
737-
debug_msg("Allocated socket #{}".format(sock), self._debug)
738-
return sock
758+
# Call garbage collection to encourage socket.__del__() be called to on any
759+
# destroyed instances. Not at all guaranteed to work!
760+
gc.collect()
761+
debug_msg(
762+
"Reserved sockets: {}".format(WIZNET5K._sockets_reserved), self._debug
763+
)
764+
765+
for socket_number, reserved in enumerate(WIZNET5K._sockets_reserved, start=1):
766+
if (
767+
not reserved
768+
and self.socket_status(socket_number)[0] == SNSR_SOCK_CLOSED
769+
):
770+
if reserve_socket:
771+
WIZNET5K._sockets_reserved[socket_number - 1] = True
772+
debug_msg(
773+
"Allocated socket # {}.".format(socket_number),
774+
self._debug,
775+
)
776+
return socket_number
777+
raise RuntimeError("Out of sockets.")
778+
779+
@staticmethod
780+
def release_socket(socket_number):
781+
"""
782+
Update the socket reservation list when a socket is no longer reserved.
783+
784+
:param int socket_number: The socket to release.
785+
"""
786+
WIZNET5K._sockets_reserved[socket_number - 1] = False
739787

740788
def socket_listen(
741789
self, socket_num: int, port: int, conn_mode: int = _SNMR_TCP
@@ -831,7 +879,7 @@ def socket_open(self, socket_num: int, conn_mode: int = _SNMR_TCP) -> int:
831879
time.sleep(0.00025)
832880

833881
self.write_snmr(socket_num, conn_mode)
834-
self._write_snir(socket_num, 0xFF)
882+
self.write_snir(socket_num, 0xFF)
835883

836884
if self.src_port > 0:
837885
# write to socket source port
@@ -893,7 +941,6 @@ def socket_read(self, socket_num: int, length: int) -> Tuple[int, bytes]:
893941
raise ValueError("Provided socket exceeds max_sockets.")
894942

895943
# Check if there is data available on the socket
896-
resp = b""
897944
ret = self._get_rx_rcv_size(socket_num)
898945
debug_msg("Bytes avail. on sock: {}".format(ret), self._debug)
899946
if ret == 0:
@@ -980,10 +1027,8 @@ def socket_write(
9801027
# pylint: disable=too-many-branches
9811028
if not self.link_status:
9821029
raise ConnectionError("Ethernet cable disconnected!")
983-
assert socket_num <= self.max_sockets, "Provided socket exceeds max_sockets."
984-
status = 0
985-
ret = 0
986-
free_size = 0
1030+
if socket_num > self.max_sockets:
1031+
raise ValueError("Provided socket exceeds max_sockets.")
9871032
if len(buffer) > _SOCK_SIZE:
9881033
ret = _SOCK_SIZE
9891034
else:
@@ -1045,12 +1090,12 @@ def socket_write(
10451090
raise RuntimeError("Socket closed before data was sent.")
10461091
if timeout and time.monotonic() - stamp > timeout:
10471092
raise RuntimeError("Operation timed out. No data sent.")
1048-
if self.read_snir(socket_num)[0] & _SNIR_TIMEOUT:
1093+
if self.read_snir(socket_num)[0] & SNIR_TIMEOUT:
10491094
raise TimeoutError(
10501095
"Hardware timeout while sending on socket {}.".format(socket_num)
10511096
)
10521097
time.sleep(0.001)
1053-
self._write_snir(socket_num, _SNIR_SEND_OK)
1098+
self.write_snir(socket_num, _SNIR_SEND_OK)
10541099
return ret
10551100

10561101
# Socket-Register Methods
@@ -1137,7 +1182,7 @@ def write_snmr(self, sock: int, protocol: int) -> None:
11371182
"""Write to Socket n Mode Register."""
11381183
self._write_socket(sock, _REG_SNMR, protocol)
11391184

1140-
def _write_snir(self, sock: int, data: int) -> None:
1185+
def write_snir(self, sock: int, data: int) -> None:
11411186
"""Write to Socket n Interrupt Register."""
11421187
self._write_socket(sock, _REG_SNIR, data)
11431188

0 commit comments

Comments
 (0)