Skyward boardcore
Loading...
Searching...
No Matches
WIZ5500.cpp
Go to the documentation of this file.
1/* Copyright (c) 2023 Skyward Experimental Rocketry
2 * Author: Davide Mor
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 * THE SOFTWARE.
21 */
22
23#include "WIZ5500.h"
24
26#include <interfaces/endianness.h>
27#include <kernel/scheduler/scheduler.h>
28#include <utils/TimeUtils.h>
29
30#include <algorithm>
31
32#include "WIZ5500Defs.h"
33#include "kernel/kernel.h"
34
35using namespace Boardcore;
36using namespace miosix;
37
38// Keep a 500ms timeout even for the general INTn
39constexpr long long INTN_TIMEOUT = 500 * 1000 * 1000;
40
41static long long intoUntil(int timeout)
42{
43 return timeout == -1 ? -1 : getTime() + msToNs(timeout);
44}
45
46static SPIBusConfig getSpiBusConfig(SPI::ClockDivider clock_divider)
47{
48 SPIBusConfig bus_config = {};
49 bus_config.clockDivider = clock_divider;
50 bus_config.mode = SPI::Mode::MODE_0;
51 bus_config.bitOrder = SPI::Order::MSB_FIRST;
52 bus_config.byteOrder = SPI::Order::MSB_FIRST;
53
54 return bus_config;
55}
56
57Wiz5500::Wiz5500(SPIBus& bus, miosix::GpioPin cs, miosix::GpioPin intn,
58 SPI::ClockDivider clock_divider)
59 : intn(intn), slave(bus, cs, getSpiBusConfig(clock_divider))
60{
62
63 // Reset thread wait infos
64 for (int i = 0; i < NUM_THREAD_WAIT_INFOS; i++)
65 {
66 wait_infos[i].sock_n = -1;
67 wait_infos[i].irq_mask = 0;
68 wait_infos[i].irq = 0;
69 wait_infos[i].thread = nullptr;
70 }
71
72 // Reset socket infos
73 for (int i = 0; i < NUM_SOCKETS; i++)
74 {
75 socket_infos[i].mode = Wiz5500::SocketMode::CLOSED;
76 socket_infos[i].irq_mask = 0;
77 }
78}
79
81
83{
84 Lock<FastMutex> l(mutex);
85 on_ip_conflict = cb;
86}
87
89{
90 Lock<FastMutex> l(mutex);
91 on_dest_unreachable = cb;
92}
93
95{
96 Lock<FastMutex> l(mutex);
97
98 return spiRead8(0, Wiz::Common::REG_VERSIONR) == Wiz::VERSION;
99}
100
102{
103 Lock<FastMutex> l(mutex);
104 uint8_t phycfg = spiRead8(0, Wiz::Common::REG_PHYCFGR);
105
106 bool full_duplex = (phycfg & (1 << 2)) != 0;
107 bool based_100mbps = (phycfg & (1 << 1)) != 0;
108 bool link_up = (phycfg & (1 << 0)) != 0;
109
110 return {full_duplex, based_100mbps, link_up};
111}
112
114{
115 Lock<FastMutex> l(mutex);
116
117 // Perform a software reset
118 spiWrite8(0, Wiz::Common::REG_MR, 1 << 7);
119 // Enable all socket interrupts
120 spiWrite8(0, Wiz::Common::REG_SIMR, 0b11111111);
121 spiWrite8(0, Wiz::Common::REG_IMR, 0b11110000);
122
123 // Reset all socketsOSI
124 for (int i = 0; i < NUM_SOCKETS; i++)
126}
127
129{
130 if (intn_thread)
131 {
132 intn_thread->IRQwakeup();
133 if (intn_thread->IRQgetPriority() >
134 miosix::Thread::IRQgetCurrentThread()->IRQgetPriority())
135 {
136 miosix::Scheduler::IRQfindNextThread();
137 }
138 }
139}
140
142{
143 Lock<FastMutex> l(mutex);
144 spiWriteIp(0, Wiz::Common::REG_GAR, ip);
145}
146
148{
149 Lock<FastMutex> l(mutex);
150 spiWriteIp(0, Wiz::Common::REG_SUBR, mask);
151}
152
154{
155 Lock<FastMutex> l(mutex);
156 spiWriteMac(0, Wiz::Common::REG_SHAR, mac);
157}
158
160{
161 Lock<FastMutex> l(mutex);
162 spiWriteIp(0, Wiz::Common::REG_SIPR, ip);
163}
164
165bool Wiz5500::connectTcp(int sock_n, uint16_t src_port, WizIp dst_ip,
166 uint16_t dst_port, int timeout)
167{
168 // First convert timeout into until
169 long long until = intoUntil(timeout);
170
171 Lock<FastMutex> l(mutex);
172
173 // Check that we are closed
174 if (socket_infos[sock_n].mode != Wiz5500::SocketMode::CLOSED)
175 return false;
176
177 // Setup the socket
180 spiWrite16(Wiz::getSocketRegBlock(sock_n), Wiz::Socket::REG_PORT, src_port);
181 spiWriteIp(Wiz::getSocketRegBlock(sock_n), Wiz::Socket::REG_DIPR, dst_ip);
183 dst_port);
184
185 // Open the socket
188
189 // Ok now check that we actually went into that mode
190 int status = spiRead8(Wiz::getSocketRegBlock(sock_n), Wiz::Socket::REG_SR);
191 if (status != Wiz::Socket::STAT_INIT)
192 return false;
193
194 // Connect the socket
197
198 // Ok now wait for either a connection, or a disconnection
199 int irq = waitForSocketIrq(
200 l, sock_n, Wiz::Socket::Irq::CON | Wiz::Socket::Irq::DISCON, until);
201
202 // Connection failed
203 if ((irq & Wiz::Socket::Irq::CON) == 0)
204 return false;
205
206 socket_infos[sock_n].mode = Wiz5500::SocketMode::TCP;
207 return true;
208}
209
210bool Wiz5500::listenTcp(int sock_n, uint16_t src_port, WizIp& dst_ip,
211 uint16_t& dst_port, int timeout)
212{
213 // First convert timeout into until
214 long long until = intoUntil(timeout);
215
216 Lock<FastMutex> l(mutex);
217
218 // Check that we are closed
219 if (socket_infos[sock_n].mode != Wiz5500::SocketMode::CLOSED)
220 return false;
221
222 // Setup the socket
225 spiWrite16(Wiz::getSocketRegBlock(sock_n), Wiz::Socket::REG_PORT, src_port);
226
227 // Open the socket
230
231 // Ok now check that we actually went into that mode
232 int status = spiRead8(Wiz::getSocketRegBlock(sock_n), Wiz::Socket::REG_SR);
233 if (status != Wiz::Socket::STAT_INIT)
234 return false;
235
236 // Connect the socket
239
240 // Ok now wait for either a connection, or a disconnection
241 int irq =
242 waitForSocketIrq(l, sock_n,
243 Wiz::Socket::Irq::CON | Wiz::Socket::Irq::DISCON |
244 Wiz::Socket::Irq::TIMEOUT,
245 until);
246
247 // Connection failed
248 if ((irq & Wiz::Socket::Irq::CON) == 0)
249 return false;
250
251 // Read remote side infos
252 dst_ip = spiReadIp(Wiz::getSocketRegBlock(sock_n), Wiz::Socket::REG_DIPR);
253 dst_port =
255
256 socket_infos[sock_n].mode = Wiz5500::SocketMode::TCP;
257 return true;
258}
259
260bool Wiz5500::openUdp(int sock_n, uint16_t src_port, WizIp dst_ip,
261 uint16_t dst_port, int timeout)
262{
263 // For now the timeout is unused
264 (void)timeout;
265
266 Lock<FastMutex> l(mutex);
267
268 // Check that we are closed
269 if (socket_infos[sock_n].mode != Wiz5500::SocketMode::CLOSED)
270 return false;
271
272 // Setup the socket
274 Wiz::Socket::buildModeUdp(false, false, false, false));
275 spiWrite16(Wiz::getSocketRegBlock(sock_n), Wiz::Socket::REG_PORT, src_port);
276 spiWriteIp(Wiz::getSocketRegBlock(sock_n), Wiz::Socket::REG_DIPR, dst_ip);
278 dst_port);
279
280 // Open the socket
283
284 // Ok now check that we actually went into that mode
285 int status = spiRead8(Wiz::getSocketRegBlock(sock_n), Wiz::Socket::REG_SR);
286 if (status != Wiz::Socket::STAT_UDP)
287 return false;
288
289 socket_infos[sock_n].mode = Wiz5500::SocketMode::UDP;
290 return true;
291}
292
293bool Wiz5500::send(int sock_n, const uint8_t* data, size_t len, int timeout)
294{
295 // First convert timeout into until
296 long long until = intoUntil(timeout);
297
298 Lock<FastMutex> l(mutex);
299
300 // We cannot send through a closed socket
301 if (socket_infos[sock_n].mode == Wiz5500::SocketMode::CLOSED)
302 return false;
303
304 // First get the start write address
305 uint16_t start_addr =
307
308 // Fill the TX buffer and update the counter
309 spiWrite(Wiz::getSocketTxBlock(sock_n), start_addr, data, len);
311 start_addr + len);
312
313 // Finally tell the device to send the data
316
317 // Wait for the device to signal a correct send
318 int irq = waitForSocketIrq(l, sock_n, Wiz::Socket::Irq::SEND_OK, until);
319
320 // It didn't signal it as an error
321 if ((irq & Wiz::Socket::Irq::SEND_OK) == 0)
322 return false;
323
324 return true;
325}
326
327ssize_t Wiz5500::recv(int sock_n, uint8_t* data, size_t len, int timeout)
328{
329 // First convert timeout into until
330 long long until = intoUntil(timeout);
331
332 Lock<FastMutex> l(mutex);
333
334 // This is only valid for TCP
335 if (socket_infos[sock_n].mode != Wiz5500::SocketMode::TCP)
336 return -1;
337
338 // Wait for the device to signal that we received something, or a
339 // disconnection
340 int irq = waitForSocketIrq(
341 l, sock_n, Wiz::Socket::Irq::RECV | Wiz::Socket::Irq::DISCON, until);
342 if ((irq & Wiz::Socket::Irq::RECV) == 0)
343 return -1;
344
345 // Ok we received something, get the received length
346 uint16_t recv_len =
348 uint16_t addr =
350
351 // Check if we actually have space
352 if (recv_len < len)
353 spiRead(Wiz::getSocketRxBlock(sock_n), addr, data, recv_len);
354
355 addr += recv_len;
356 spiWrite16(Wiz::getSocketRegBlock(sock_n), Wiz::Socket::REG_RX_RD, addr);
357
358 // Finally tell the device that we correctly received and read the data
361
362 return recv_len < len ? recv_len : -1;
363}
364
365ssize_t Wiz5500::recvfrom(int sock_n, uint8_t* data, size_t len, WizIp& dst_ip,
366 uint16_t& dst_port, int timeout)
367{
368 // First convert timeout into until
369 long long until = intoUntil(timeout);
370
371 Lock<FastMutex> l(mutex);
372
373 // This is only valid for UDP
374 if (socket_infos[sock_n].mode != Wiz5500::SocketMode::UDP)
375 return -1;
376
377 // Wait for the device to signal that we received something, or a
378 // disconnection
379 int irq = waitForSocketIrq(
380 l, sock_n, Wiz::Socket::Irq::RECV | Wiz::Socket::Irq::DISCON, until);
381 if ((irq & Wiz::Socket::Irq::RECV) == 0)
382 return -1;
383
384 // Ok we received something, get the received length
385 uint16_t recv_len =
387 uint16_t addr =
389
390 // First read the internal header
391 spiRead(Wiz::getSocketRxBlock(sock_n), addr,
392 reinterpret_cast<uint8_t*>(&dst_ip), sizeof(WizIp));
393 addr += sizeof(WizIp);
394 spiRead(Wiz::getSocketRxBlock(sock_n), addr,
395 reinterpret_cast<uint8_t*>(&dst_port), sizeof(uint16_t));
396 addr += sizeof(uint16_t);
397
398 // Now, what's this?
399 uint16_t what = 0;
400 spiRead(Wiz::getSocketRxBlock(sock_n), addr,
401 reinterpret_cast<uint8_t*>(&what), sizeof(uint16_t));
402 addr += sizeof(uint16_t);
403
404 // Remove what we have already read.
405 recv_len -= sizeof(WizIp) + sizeof(uint16_t) + sizeof(uint16_t);
406
407 // Read up to the user-provided size, or all received data if smaller
408 uint16_t read_len = std::min(static_cast<size_t>(recv_len), len);
409
410 spiRead(Wiz::getSocketRxBlock(sock_n), addr, data, read_len);
411
412 addr += recv_len;
413 spiWrite16(Wiz::getSocketRegBlock(sock_n), Wiz::Socket::REG_RX_RD, addr);
414
415 // Finally tell the device that we correctly received and read the data
418
419 return read_len;
420}
421
422void Wiz5500::close(int sock_n, int timeout)
423{
424 // First convert timeout into until
425 long long until = intoUntil(timeout);
426
427 Lock<FastMutex> l(mutex);
428
429 // We cannot receive close a closed socket
430 if (socket_infos[sock_n].mode == Wiz5500::SocketMode::CLOSED)
431 return;
432
435
436 waitForSocketIrq(l, sock_n, Wiz::Socket::Irq::DISCON, until);
437 socket_infos[sock_n].mode = Wiz5500::SocketMode::CLOSED;
438}
439
440TimedWaitResult Wiz5500::waitForINTn(Lock<FastMutex>& l, long long until)
441{
442 TimedWaitResult result = TimedWaitResult::NoTimeout;
443
444 Unlock<FastMutex> ul(l);
445 FastInterruptDisableLock il;
446
447 intn_thread = Thread::IRQgetCurrentThread();
448
449 while (intn.value() != 0 && result == TimedWaitResult::NoTimeout)
450 {
451 long long now = getTime();
452 if (until == -1 || until > (now + INTN_TIMEOUT))
453 {
454 // The timeout either doesn't exist, or it's further in time
455 Thread::IRQenableIrqAndTimedWait(il, now + INTN_TIMEOUT);
456 }
457 else
458 {
459 // If we timeout here, we actually reached the final timeout
460 result = Thread::IRQenableIrqAndTimedWait(il, until);
461 }
462 }
463
464 // Set the thread pointer to null just to make sure
465 intn_thread = nullptr;
466
467 return result;
468}
469
470int Wiz5500::waitForSocketIrq(miosix::Lock<miosix::FastMutex>& l, int sock_n,
471 uint8_t irq_mask, long long until)
472{
473 // Check that someone else isn't already waiting for one of ours interrupts
474 if ((socket_infos[sock_n].irq_mask & irq_mask) != 0)
475 return 0;
476
477 // Enable the interrupts requested, updating the IRQ mask
478 socket_infos[sock_n].irq_mask |= irq_mask;
480 socket_infos[sock_n].irq_mask);
481
482 Thread* this_thread = Thread::getCurrentThread();
483
484 // Find a free slot in the data structure
485 int i = 0;
486 while (i < NUM_THREAD_WAIT_INFOS)
487 {
488 if (wait_infos[i].sock_n == -1)
489 {
490 wait_infos[i].sock_n = sock_n;
491 wait_infos[i].irq_mask = irq_mask;
492 wait_infos[i].irq = 0;
493 wait_infos[i].thread = this_thread;
494 break;
495 }
496
497 i++;
498 }
499
500 // We didn't find any, return with failure
501 if (i == NUM_THREAD_WAIT_INFOS)
502 return 0;
503
504 TimedWaitResult result = TimedWaitResult::NoTimeout;
505
506 if (interrupt_service_thread != nullptr)
507 {
508 // There is already someone managing interrupts for us, just wait
509 while (wait_infos[i].irq == 0 && result == TimedWaitResult::NoTimeout &&
510 interrupt_service_thread != this_thread)
511 {
512 if (until != -1)
513 {
514 Unlock<FastMutex> ul(l);
515 result = Thread::timedWait(until);
516 }
517 else
518 {
519 Unlock<FastMutex> ul(l);
520 Thread::wait();
521 }
522 }
523 }
524 else
525 {
526 // Nobody is managing interrupts, we are doing it ourself
527 interrupt_service_thread = this_thread;
528 }
529
530 while (interrupt_service_thread == this_thread)
531 {
532 // Run a single step of the ISR
533 result = runInterruptServiceRoutine(l, until);
534
535 // Check if we woke up ourself, or we reached a timeout, then we need to
536 // elect a new interrupt service thread
537 if (wait_infos[i].irq != 0 || result == TimedWaitResult::Timeout)
538 {
539 Thread* new_interrupt_service_thread = nullptr;
540
541 for (int j = 0; j < NUM_THREAD_WAIT_INFOS; j++)
542 {
543 if (wait_infos[j].irq == 0 && wait_infos[j].sock_n != -1 &&
544 j != i)
545 {
546 new_interrupt_service_thread = wait_infos[j].thread;
547 break;
548 }
549 }
550
551 // Pick a new IST, if none is found, no-one is waiting, and the IST
552 // is not necessary
553 interrupt_service_thread = new_interrupt_service_thread;
554 if (interrupt_service_thread)
555 interrupt_service_thread->wakeup();
556 }
557 }
558
559 // The interrupt arrived, clear the slot
560 wait_infos[i].sock_n = -1;
561
562 // Disable the interrupts
563 socket_infos[sock_n].irq_mask &= ~irq_mask;
565 socket_infos[sock_n].irq_mask);
566
567 return wait_infos[i].irq;
568}
569
570TimedWaitResult Wiz5500::runInterruptServiceRoutine(Lock<FastMutex>& l,
571 long long until)
572{
573 // Wait for an interrupt, returning to the caller the possible timeout
574 if (waitForINTn(l, until) == TimedWaitResult::Timeout)
575 return TimedWaitResult::Timeout;
576
577 // Ok something happened!
578
579 // First check for general interrupts
580 uint8_t ir = spiRead8(0, Wiz::Common::REG_IR);
581 spiWrite8(0, Wiz::Common::REG_IR, ir);
582
583 uint8_t sn_ir[NUM_SOCKETS] = {};
584
585 // Then check for interrupt on all the sockets
586 uint8_t sir = spiRead8(0, Wiz::Common::REG_SIR);
587 for (int i = 0; i < NUM_SOCKETS; i++)
588 {
589 if (sir & (1 << i))
590 {
591 sn_ir[i] = spiRead8(Wiz::getSocketRegBlock(i), Wiz::Socket::REG_IR);
592 spiWrite8(Wiz::getSocketRegBlock(i), Wiz::Socket::REG_IR, sn_ir[i]);
593 }
594 }
595
596 // Ok now wake up all threads in sleep
597 for (int i = 0; i < NUM_THREAD_WAIT_INFOS; i++)
598 {
599 if (wait_infos[i].sock_n != -1)
600 {
601 int sock_n = wait_infos[i].sock_n;
602 int irq = sn_ir[sock_n] & wait_infos[i].irq_mask;
603
604 if (irq != 0)
605 {
606 wait_infos[i].irq = irq;
607 wait_infos[i].thread->wakeup();
608 }
609 }
610 }
611
612 // Dispatch generic interrupts
613 if (ir & Wiz::Common::Irq::CONFLICT)
614 {
615 auto cb = on_ip_conflict;
616 if (cb)
617 {
618 Unlock<FastMutex> ul(l);
619 cb();
620 }
621 }
622
623 if (ir & Wiz::Common::Irq::UNREACH)
624 {
625 auto cb = on_dest_unreachable;
626 if (cb)
627 {
628 WizIp ip = spiReadIp(0, Wiz::Common::REG_UIPR);
629 uint16_t port = spiRead16(0, Wiz::Common::REG_UPORTR);
630
631 Unlock<FastMutex> ul(l);
632 cb(ip, port);
633 }
634 }
635
636 return TimedWaitResult::NoTimeout;
637}
638
639void Wiz5500::spiRead(uint8_t block, uint16_t address, uint8_t* data,
640 size_t len)
641{
642 // Do a manual SPI transaction
643 slave.bus.configure(slave.config);
644
645 slave.bus.select(slave.cs);
646 slave.bus.write16(address);
647 slave.bus.write(Wiz::buildControlWord(block, false));
648 slave.bus.read(data, len);
649 slave.bus.deselect(slave.cs);
650}
651
652void Wiz5500::spiWrite(uint8_t block, uint16_t address, const uint8_t* data,
653 size_t len)
654{
655 // Do a manual SPI transaction
656 slave.bus.configure(slave.config);
657
658 slave.bus.select(slave.cs);
659 slave.bus.write16(address);
660 slave.bus.write(Wiz::buildControlWord(block, true));
661 slave.bus.write(data, len);
662 slave.bus.deselect(slave.cs);
663}
664
665uint8_t Wiz5500::spiRead8(uint8_t block, uint16_t address)
666{
667 uint8_t data;
668 spiRead(block, address, &data, 1);
669 return data;
670}
671
672uint16_t Wiz5500::spiRead16(uint8_t block, uint16_t address)
673{
674 uint16_t data;
675 spiRead(block, address, reinterpret_cast<uint8_t*>(&data),
676 sizeof(uint16_t));
677 return fromBigEndian16(data);
678}
679
680WizIp Wiz5500::spiReadIp(uint8_t block, uint16_t address)
681{
682 WizIp data;
683 spiRead(block, address, reinterpret_cast<uint8_t*>(&data), sizeof(WizIp));
684 return data;
685}
686
687/*WizMac Wiz5500::spiReadMac(uint8_t block, uint16_t address)
688{
689 WizMac data;
690 spiRead(block, address, reinterpret_cast<uint8_t *>(&data), sizeof(WizMac));
691 return data;
692}*/
693
694void Wiz5500::spiWrite8(uint8_t block, uint16_t address, uint8_t data)
695{
696 spiWrite(block, address, &data, 1);
697}
698
699void Wiz5500::spiWrite16(uint8_t block, uint16_t address, uint16_t data)
700{
701 data = toBigEndian16(data);
702 spiWrite(block, address, reinterpret_cast<uint8_t*>(&data),
703 sizeof(uint16_t));
704}
705
706void Wiz5500::spiWriteIp(uint8_t block, uint16_t address, WizIp data)
707{
708 spiWrite(block, address, reinterpret_cast<uint8_t*>(&data), sizeof(WizIp));
709}
710
711void Wiz5500::spiWriteMac(uint8_t block, uint16_t address, WizMac data)
712{
713 spiWrite(block, address, reinterpret_cast<uint8_t*>(&data), sizeof(WizMac));
714}
constexpr long long INTN_TIMEOUT
Definition WIZ5500.cpp:39
Driver for STM32 low level SPI peripheral.
Definition SPIBus.h:61
virtual void write16(uint16_t data)=0
Writes 16 bits to the bus.
virtual void deselect(GpioType cs)=0
Deselects the slave.
virtual uint8_t read()=0
Reads 8 bits from the bus.
virtual void select(GpioType cs)=0
Selects the slave.
virtual void write(uint8_t data)=0
Writes 8 bits to the bus.
virtual void configure(SPIBusConfig config)=0
Configures the bus with the provided configuration parameters.
ssize_t recvfrom(int sock_n, uint8_t *data, size_t len, WizIp &dst_ip, uint16_t &dst_port, int timeout=-1)
Receive data from the socket (works only in UDP).
Definition WIZ5500.cpp:365
std::function< void()> OnIpConflictCb
Definition WIZ5500.h:64
void setSourceIp(WizIp ip)
Set the device IP address.
Definition WIZ5500.cpp:159
bool openUdp(int sock_n, uint16_t src_port, WizIp dst_ip, uint16_t dst_port, int timeout=-1)
Open a simple UDP socket.
Definition WIZ5500.cpp:260
void setSourceMac(WizMac mac)
Set the device MAC address.
Definition WIZ5500.cpp:153
void setOnIpConflict(OnIpConflictCb cb)
Sets the callback to be invoked when the device detects an IP. conflict.
Definition WIZ5500.cpp:82
std::function< void(WizIp, uint16_t)> OnDestUnreachableCb
Definition WIZ5500.h:65
bool checkVersion()
Checks the VERSION register. Can be used to detect device presence.
Definition WIZ5500.cpp:94
void setGatewayIp(WizIp ip)
Set global gateway ip.
Definition WIZ5500.cpp:141
void reset()
Resets the device. Performs a software resets, resetting all registers and closing all sockets.
Definition WIZ5500.cpp:113
bool listenTcp(int sock_n, uint16_t src_port, WizIp &dst_ip, uint16_t &dst_port, int timeout=-1)
Listen for a single remote TCP connection.
Definition WIZ5500.cpp:210
void handleINTn()
Handle an interrupt from INTn.
Definition WIZ5500.cpp:128
Wiz5500(SPIBus &bus, miosix::GpioPin cs, miosix::GpioPin intn, SPI::ClockDivider clock_divider)
Build an instance of the driver.
Definition WIZ5500.cpp:57
ssize_t recv(int sock_n, uint8_t *data, size_t len, int timeout=-1)
Receive data from the socket (works only in TCP).
Definition WIZ5500.cpp:327
void setSubnetMask(WizIp mask)
Set global subnet mask.
Definition WIZ5500.cpp:147
void setOnDestUnreachable(OnDestUnreachableCb cb)
Sets the callback to be invoked when the device detects an unreachable host.
Definition WIZ5500.cpp:88
bool send(int sock_n, const uint8_t *data, size_t len, int timeout=-1)
Send data through the socket (works both in TCP and UDP).
Definition WIZ5500.cpp:293
PhyState getPhyState()
Get current PHY state, can be used to poll link status, and wait for link up.
Definition WIZ5500.cpp:101
void close(int sock_n, int timeout=-1)
Close a socket.
Definition WIZ5500.cpp:422
bool connectTcp(int sock_n, uint16_t src_port, WizIp dst_ip, uint16_t dst_port, int timeout=-1)
Connect to a remote socket via TCP.
Definition WIZ5500.cpp:165
void disableExternalInterrupt(unsigned int gpioPort, unsigned int gpioNum)
Disables external interrupts on the provided pin.
void enableExternalInterrupt(unsigned int gpioPort, unsigned int gpioNum, InterruptTrigger trigger, unsigned int priority)
Enables external interrupts on the provided pin. Remember to set the GPIO to input mode!
ClockDivider
SPI Clock divider.
Definition SPIDefs.h:70
uint8_t buildModeTcp(bool enable_no_delayed_ack)
uint8_t buildModeUdp(bool enable_multicast, bool block_broadcast, bool multicast_use_igmp_v1, bool block_unicast)
uint8_t buildControlWord(uint8_t block, bool write)
Definition WIZ5500Defs.h:35
uint8_t getSocketTxBlock(int n)
Definition WIZ5500Defs.h:42
uint8_t getSocketRxBlock(int n)
Definition WIZ5500Defs.h:44
uint8_t getSocketRegBlock(int n)
Definition WIZ5500Defs.h:40
This file includes all the types the logdecoder script will decode.
long long now()
Definition SX1278Fsk.cpp:38
constexpr long long msToNs(long long ms)
Convert milliseconds to nanoseconds.
Definition TimeUtils.h:56
SPI Bus configuration for a specific slave.
SPI::ClockDivider clockDivider
< Peripheral clock division
GpioType cs
Chip select pin.
SPIBusInterface & bus
Bus on which the slave is connected.
Class representing an IPv4 ip.
Definition WIZ5500.h:38
Class representing an ethernet MAC address.
Definition WIZ5500.h:46