|
45 | 45 |
|
46 | 46 | from random import randint
|
47 | 47 | import time
|
| 48 | +import gc |
48 | 49 | from micropython import const
|
49 | 50 |
|
50 | 51 | from adafruit_bus_device.spi_device import SPIDevice
|
51 | 52 | import adafruit_wiznet5k.adafruit_wiznet5k_dhcp as dhcp
|
52 | 53 | import adafruit_wiznet5k.adafruit_wiznet5k_dns as dns
|
| 54 | +from adafruit_wiznet5k.adafruit_wiznet5k_debug import debug_msg |
53 | 55 |
|
54 | 56 | # Wiznet5k Registers
|
55 | 57 | _REG_MR = const(0x0000) # Mode
|
@@ -144,6 +146,8 @@ class WIZNET5K: # pylint: disable=too-many-public-methods, too-many-instance-at
|
144 | 146 | _UDP_MODE = const(0x02)
|
145 | 147 | _TLS_MODE = const(0x03) # This is NOT currently implemented
|
146 | 148 |
|
| 149 | + _sockets_reserved = [] |
| 150 | + |
147 | 151 | # pylint: disable=too-many-arguments
|
148 | 152 | def __init__(
|
149 | 153 | self,
|
@@ -722,26 +726,61 @@ def _send_socket_cmd(self, socket: int, cmd: int) -> None:
|
722 | 726 | if self._debug:
|
723 | 727 | print("waiting for sncr to clear...")
|
724 | 728 |
|
725 |
| - def get_socket(self) -> int: |
726 |
| - """Request, allocate and return a socket from the W5k chip. |
| 729 | + def get_socket(self, *, reserve_socket=False) -> int: |
| 730 | + """ |
| 731 | + Request, allocate and return a socket from the W5k chip. |
| 732 | +
|
| 733 | + Cycle through the sockets to find the first available one. If the called with |
| 734 | + reserve_socket=True, update the list of reserved sockets (intended to be used with |
| 735 | + socket.socket()). Note that reserved sockets must be released by calling |
| 736 | + cancel_reservation() once they are no longer needed. |
| 737 | +
|
| 738 | + If all sockets are reserved, no sockets are available for DNS calls, etc. Therefore, |
| 739 | + one socket cannot be reserved. Since socket 0 is the only socket that is capable of |
| 740 | + operating in MacRAW mode, it is the non-reservable socket. |
727 | 741 |
|
728 |
| - Cycle through the sockets to find the first available one, if any. |
| 742 | + :param bool reserve_socket: Whether to reserve the socket. |
729 | 743 |
|
730 |
| - :return int: The first available socket. Returns 0xFF if no sockets are free. |
| 744 | + :returns int: The first available socket. |
| 745 | +
|
| 746 | + :raises RuntimeError: If no socket is available. |
731 | 747 | """
|
732 |
| - if self._debug: |
733 |
| - print("*** Get socket") |
| 748 | + debug_msg("*** Get socket.", self._debug) |
| 749 | + # Prefer socket zero for none reserved calls as it cannot be reserved. |
| 750 | + if not reserve_socket and self.socket_status(0)[0] == SNSR_SOCK_CLOSED: |
| 751 | + debug_msg("Allocated socket # 0", self._debug) |
| 752 | + return 0 |
| 753 | + # Then check the other sockets. |
734 | 754 |
|
735 |
| - sock = _SOCKET_INVALID |
736 |
| - for _sock in range(self.max_sockets): |
737 |
| - status = self.socket_status(_sock)[0] |
738 |
| - if status == SNSR_SOCK_CLOSED: |
739 |
| - sock = _sock |
740 |
| - break |
| 755 | + # Call garbage collection to encourage socket.__del__() be called to on any |
| 756 | + # destroyed instances. Not at all guaranteed to work! |
| 757 | + gc.collect() |
| 758 | + debug_msg( |
| 759 | + "Reserved sockets: {}".format(WIZNET5K._sockets_reserved), self._debug |
| 760 | + ) |
741 | 761 |
|
742 |
| - if self._debug: |
743 |
| - print("Allocated socket #{}".format(sock)) |
744 |
| - return sock |
| 762 | + for socket_number, reserved in enumerate(WIZNET5K._sockets_reserved, start=1): |
| 763 | + if ( |
| 764 | + not reserved |
| 765 | + and self.socket_status(socket_number)[0] == SNSR_SOCK_CLOSED |
| 766 | + ): |
| 767 | + if reserve_socket: |
| 768 | + WIZNET5K._sockets_reserved[socket_number - 1] = True |
| 769 | + debug_msg( |
| 770 | + "Allocated socket # {}.".format(socket_number), |
| 771 | + self._debug, |
| 772 | + ) |
| 773 | + return socket_number |
| 774 | + raise RuntimeError("Out of sockets.") |
| 775 | + |
| 776 | + @staticmethod |
| 777 | + def release_socket(socket_number): |
| 778 | + """ |
| 779 | + Update the socket reservation list when a socket is no longer reserved. |
| 780 | +
|
| 781 | + :param int socket_number: The socket to release. |
| 782 | + """ |
| 783 | + WIZNET5K._sockets_reserved[socket_number] = False |
745 | 784 |
|
746 | 785 | def socket_listen(
|
747 | 786 | self, socket_num: int, port: int, conn_mode: int = _SNMR_TCP
|
|
0 commit comments