Skip to content

Commit b956c4b

Browse files
stracciofpistm
authored andcommitted
Added multicast udp, added callback for interrupt data arrival
Implemented begin multicast for receiving multicast udp. Added ability to add a callback from the interrupt when udp receive data (Usefull with FreeRTOS). ``` void EthernetUDP::onDataArrival( std::function<void()> onDataArrival_fn){ _udp.onDataArrival = onDataArrival_fn; } ```
1 parent 07b3797 commit b956c4b

File tree

6 files changed

+130
-31
lines changed

6 files changed

+130
-31
lines changed

src/EthernetUdp.cpp

100644100755
+28-7
Original file line numberDiff line numberDiff line change
@@ -25,16 +25,23 @@
2525
*
2626
* [email protected] 12/30/2008
2727
*/
28-
2928
#include "STM32Ethernet.h"
3029
#include "Udp.h"
3130
#include "Dns.h"
3231

32+
#include "lwip/igmp.h"
33+
#include "lwip/ip_addr.h"
34+
3335
/* Constructor */
3436
EthernetUDP::EthernetUDP() {}
3537

3638
/* Start EthernetUDP socket, listening at local port PORT */
3739
uint8_t EthernetUDP::begin(uint16_t port) {
40+
return begin(Ethernet.localIP(), port);
41+
}
42+
43+
/* Start EthernetUDP socket, listening at local IP ip and port PORT */
44+
uint8_t EthernetUDP::begin(IPAddress ip, uint16_t port, bool multicast) {
3845
// Can create a single udp connection per socket
3946
if(_udp.pcb != NULL) {
4047
return 0;
@@ -46,14 +53,25 @@ uint8_t EthernetUDP::begin(uint16_t port) {
4653
return 0;
4754
}
4855

49-
IPAddress ip = Ethernet.localIP();
5056
ip_addr_t ipaddr;
57+
err_t err;
58+
u8_to_ip_addr(rawIPAddress(ip), &ipaddr);
59+
if (multicast) {
60+
err = udp_bind(_udp.pcb, IP_ADDR_ANY, port);
61+
} else {
62+
err = udp_bind(_udp.pcb, &ipaddr, port);
63+
}
5164

52-
if(ERR_OK != udp_bind(_udp.pcb, u8_to_ip_addr(rawIPAddress(ip), &ipaddr), port)) {
65+
if(ERR_OK != err) {
5366
stop();
5467
return 0;
5568
}
5669

70+
#if LWIP_IGMP
71+
if ((multicast) && (ERR_OK != igmp_joingroup(IP_ADDR_ANY, &ipaddr))) {
72+
return 0;
73+
}
74+
#endif
5775
udp_recv(_udp.pcb, &udp_receive_callback, &_udp);
5876

5977
_port = port;
@@ -104,8 +122,6 @@ int EthernetUDP::beginPacket(IPAddress ip, uint16_t port)
104122
return 0;
105123
}
106124

107-
ip_addr_t ipaddr;
108-
109125
_sendtoIP = ip;
110126
_sendtoPort = port;
111127

@@ -245,6 +261,11 @@ void EthernetUDP::flush()
245261
/* Start EthernetUDP socket, listening at local port PORT */
246262
uint8_t EthernetUDP::beginMulticast(IPAddress ip, uint16_t port)
247263
{
248-
UNUSED(ip);
249-
return begin(port);
264+
return begin(ip, port, true);
265+
}
266+
267+
#if LWIP_UDP
268+
void EthernetUDP::onDataArrival( std::function<void()> onDataArrival_fn){
269+
_udp.onDataArrival = onDataArrival_fn;
250270
}
271+
#endif

src/EthernetUdp.h

+3-2
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,9 @@
3838
#define ethernetudp_h
3939

4040
#include <Udp.h>
41+
#include <functional>
4142

42-
extern "C" {
4343
#include "utility/stm32_eth.h"
44-
}
4544

4645
#define UDP_TX_PACKET_MAX_SIZE 24
4746

@@ -62,6 +61,7 @@ class EthernetUDP : public UDP {
6261
public:
6362
EthernetUDP(); // Constructor
6463
virtual uint8_t begin(uint16_t); // initialize, start listening on specified port. Returns 1 if successful, 0 if there are no sockets available to use
64+
virtual uint8_t begin(IPAddress, uint16_t, bool multicast = false); // initialize, start listening on specified port. Returns 1 if successful, 0 if there are no sockets available to use
6565
virtual uint8_t beginMulticast(IPAddress, uint16_t); // initialize, start listening on specified port. Returns 1 if successful, 0 if there are no sockets available to use
6666
virtual void stop(); // Finish with the UDP socket
6767

@@ -104,6 +104,7 @@ class EthernetUDP : public UDP {
104104
virtual IPAddress remoteIP() { return _remoteIP; };
105105
// Return the port of the host who sent the current incoming packet
106106
virtual uint16_t remotePort() { return _remotePort; };
107+
virtual void onDataArrival( std::function<void()> onDataArrival_fn);
107108
};
108109

109110
#endif

src/utility/ethernetif.c renamed to src/utility/ethernetif.cpp

+86-1
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
#include "ethernetif.h"
5252
#include <string.h>
5353
#include "PeripheralPins.h"
54+
#include "lwip/igmp.h"
5455
#include "stm32_eth.h"
5556
#if !defined(STM32_CORE_VERSION) || (STM32_CORE_VERSION <= 0x01050000)
5657
#include "variant.h"
@@ -92,6 +93,11 @@ static ETH_HandleTypeDef EthHandle;
9293

9394
static uint8_t macaddress[6]= { MAC_ADDR0, MAC_ADDR1, MAC_ADDR2, MAC_ADDR3, MAC_ADDR4, MAC_ADDR5 };
9495

96+
#if LWIP_IGMP
97+
uint32_t ETH_HashTableHigh=0x0;
98+
uint32_t ETH_HashTableLow=0x0;
99+
#endif
100+
95101
/* Private function prototypes -----------------------------------------------*/
96102
/* Private functions ---------------------------------------------------------*/
97103
/*******************************************************************************
@@ -205,7 +211,9 @@ static void low_level_init(struct netif *netif)
205211

206212
/* Enable MAC and DMA transmission and reception */
207213
HAL_ETH_Start(&EthHandle);
208-
214+
#if LWIP_IGMP
215+
netif_set_igmp_mac_filter(netif, igmp_mac_filter);
216+
#endif
209217
/**** Configure PHY to generate an interrupt when Eth Link state changes ****/
210218
/* Read Register Configuration */
211219
HAL_ETH_ReadPHYRegister(&EthHandle, PHY_IMR, &regvalue);
@@ -214,6 +222,10 @@ static void low_level_init(struct netif *netif)
214222

215223
/* Enable Interrupt on change of link status */
216224
HAL_ETH_WritePHYRegister(&EthHandle, PHY_IMR, regvalue );
225+
#if LWIP_IGMP
226+
ETH_HashTableHigh=EthHandle.Instance->MACHTHR;
227+
ETH_HashTableLow=EthHandle.Instance->MACHTLR;
228+
#endif
217229
}
218230

219231
/**
@@ -510,6 +522,13 @@ void ethernetif_set_link(struct netif *netif)
510522
HAL_ETH_ReadPHYRegister(&EthHandle, PHY_BSR, &regvalue);
511523

512524
if((regvalue & PHY_LINKED_STATUS) != (uint16_t)RESET) {
525+
#if LWIP_IGMP
526+
if (!(netif->flags & NETIF_FLAG_IGMP)) {
527+
netif->flags |= NETIF_FLAG_IGMP;
528+
igmp_init();
529+
igmp_start(netif);
530+
}
531+
#endif
513532
netif_set_link_up(netif);
514533
}
515534
}
@@ -628,6 +647,72 @@ void ethernetif_set_mac_addr(const uint8_t *mac) {
628647
}
629648
}
630649

650+
#if LWIP_IGMP
651+
err_t igmp_mac_filter( struct netif *netif, const ip4_addr_t *ip4_addr, netif_mac_filter_action action )
652+
{
653+
uint8_t mac[6];
654+
const uint8_t *p = (const uint8_t *)ip4_addr;
655+
656+
mac[0] = 0x01;
657+
mac[1] = 0x00;
658+
mac[2] = 0x5E;
659+
mac[3] = *(p+1) & 0x7F;
660+
mac[4] = *(p+2);
661+
mac[5] = *(p+3);
662+
663+
register_multicast_address(mac);
664+
665+
return 0;
666+
}
667+
668+
#ifndef HASH_BITS
669+
#define HASH_BITS 6 /* #bits in hash */
670+
#endif
671+
672+
uint32_t ethcrc(const uint8_t *data, size_t length)
673+
{
674+
uint32_t crc = 0xffffffff;
675+
size_t i;
676+
int j;
677+
678+
for (i = 0; i < length; i++) {
679+
for (j = 0; j < 8; j++) {
680+
if (((crc >> 31) ^ (data[i] >> j)) & 0x01) {
681+
/* x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1 */
682+
crc = (crc << 1) ^ 0x04C11DB7;
683+
} else {
684+
crc = crc << 1;
685+
}
686+
}
687+
}
688+
return ~crc;
689+
}
690+
691+
void register_multicast_address(const uint8_t *mac)
692+
{
693+
uint32_t crc;
694+
uint8_t hash;
695+
696+
/* Calculate crc32 value of mac address */
697+
crc = ethcrc(mac, HASH_BITS);
698+
699+
/*
700+
* Only upper HASH_BITS are used
701+
* which point to specific bit in the hash registers
702+
*/
703+
hash = (crc >> 26) & 0x3F;
704+
705+
if (hash > 31) {
706+
ETH_HashTableHigh |= 1 << (hash - 32);
707+
EthHandle.Instance->MACHTHR = ETH_HashTableHigh;
708+
} else {
709+
ETH_HashTableLow |= 1 << hash;
710+
EthHandle.Instance->MACHTLR =ETH_HashTableLow;
711+
}
712+
}
713+
#endif /* LWIP_IGMP */
714+
715+
631716
#ifdef ETH_INPUT_USE_IT
632717
/**
633718
* @brief Ethernet Rx Transfer completed callback

src/utility/ethernetif.h

100644100755
+7-5
Original file line numberDiff line numberDiff line change
@@ -47,14 +47,11 @@
4747

4848
#ifndef __ETHERNETIF_H__
4949
#define __ETHERNETIF_H__
50-
51-
#include "lwip/err.h"
52-
#include "lwip/netif.h"
53-
5450
#ifdef __cplusplus
5551
extern "C" {
5652
#endif
57-
53+
#include "lwip/err.h"
54+
#include "lwip/netif.h"
5855
/* Exported types ------------------------------------------------------------*/
5956
uint8_t ethernetif_is_init(void);
6057
err_t ethernetif_init(struct netif *netif);
@@ -65,6 +62,11 @@ void ethernetif_notify_conn_changed(struct netif *netif);
6562

6663
void ethernetif_set_mac_addr(const uint8_t *mac);
6764

65+
#if LWIP_IGMP
66+
err_t igmp_mac_filter( struct netif *netif, const ip4_addr_t *ip4_addr, netif_mac_filter_action action );
67+
void register_multicast_address(const uint8_t *mac);
68+
#endif
69+
6870
#ifdef __cplusplus
6971
}
7072
#endif

src/utility/stm32_eth.cpp

+4-8
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,6 @@
4747
#include "lwip/prot/dhcp.h"
4848
#include "lwip/dns.h"
4949

50-
#ifdef __cplusplus
51-
extern "C" {
52-
#endif
53-
5450
/* Check ethernet link status every seconds */
5551
#define TIME_CHECK_ETH_LINK_STATE 500U
5652

@@ -798,6 +794,10 @@ void udp_receive_callback(void *arg, struct udp_pcb *pcb, struct pbuf *p,
798794

799795
ip_addr_copy(udp_arg->ip, *addr);
800796
udp_arg->port = port;
797+
798+
if(udp_arg->onDataArrival != NULL){
799+
udp_arg->onDataArrival();
800+
}
801801
} else {
802802
pbuf_free(p);
803803
}
@@ -1049,7 +1049,3 @@ void tcp_connection_close(struct tcp_pcb *tpcb, struct tcp_struct *tcp)
10491049
}
10501050

10511051
#endif /* LWIP_TCP */
1052-
1053-
#ifdef __cplusplus
1054-
}
1055-
#endif

src/utility/stm32_eth.h

+2-8
Original file line numberDiff line numberDiff line change
@@ -38,17 +38,14 @@
3838
#ifndef __STM32_ETH_H__
3939
#define __STM32_ETH_H__
4040

41-
#ifdef __cplusplus
42-
extern "C" {
43-
#endif
44-
4541
/* Includes ------------------------------------------------------------------*/
4642
#include "stm32_def.h"
4743
#include "lwip/ip_addr.h"
4844
#include "lwip/dhcp.h"
4945
#include "lwip/udp.h"
5046
#include "lwip/tcp.h"
5147
#include "lwip/opt.h"
48+
#include <functional>
5249

5350
/* Exported types ------------------------------------------------------------*/
5451
/* TCP connection state */
@@ -74,6 +71,7 @@ struct udp_struct {
7471
struct pbuf_data data;
7572
ip_addr_t ip; // the remote IP address from which the packet was received
7673
u16_t port; // the remote port from which the packet was received
74+
std::function<void()> onDataArrival;
7775
};
7876

7977
/* TCP structure */
@@ -174,8 +172,4 @@ void tcp_connection_close(struct tcp_pcb *tpcb, struct tcp_struct *tcp);
174172
#error "LWIP_TCP must be enabled in lwipopts.h"
175173
#endif
176174

177-
#ifdef __cplusplus
178-
}
179-
#endif
180-
181175
#endif /* __STM32_ETH_H__ */

0 commit comments

Comments
 (0)