реализация многоадресной рассылки LWIP на STM32F7 + FreeRTOS?

У меня есть программа LWIP клиент / сервер, которая правильно работает с одноадресной связью, однако я хочу использовать функции многоадресной рассылки, поэтому я использовал библиотеку IGMP, и сделал следующее:

1- в lwipopts.h:

#define LWIP_IGMP 1 //allowed IGMP

2- в ethernetif.c:

netif->flags |= NETIF_FLAG_IGMP; //in low_level_init function

3-в моем исходном файле (как для клиентских, так и для серверных проектов):

реализовал следующий код:

void recCallBack (void)
{
      printf("connected");  //BREAK_POINT
}
static void UDP_Multicast_init(void *arg)
{
   struct ip4_addr ipgroup, localIP;
   struct udp_pcb *g_udppcb;
   char msg[] = "hello";
   struct pbuf* p;
   p = pbuf_alloc(PBUF_TRANSPORT,sizeof(msg),PBUF_RAM);
   memcpy (p->payload, msg, sizeof(msg));

   IP4_ADDR(&ipgroup, 224, 0, 1, 129 ); //Multicast IP address.
   IP4_ADDR(&localIP, 192, 168, 1, 2); //Interface IP address
   #if LWIP_IGMP
      s8_t iret = igmp_joingroup((ip4_addr_t *)(&localIP),(ip4_addr_t *)(&ipgroup));
   #endif
   g_udppcb =( struct udp_pcb*) udp_new();
   udp_bind(g_udppcb, &localIP, 319); //to allow receiving multicast
   udp_recv(g_udppcb, recCallBack,NULL); //recCallBack is the callback function that will be called every time you    receive multicast
   udp_sendto(g_udppcb,p,&ipgroup,319); //send a multicast packet
}

void telnet_shell_init(void)
{
   sys_thread_new("TELNET", UDP_Multicast_init, NULL, DEFAULT_THREAD_STACKSIZE, osPriorityAboveNormal);
}

Результат: все упомянутые шаги кода успешно выполняются в обоих проектах (клиентском и серверном), но я не получаю никаких многоадресных сообщений (или, может быть, даже не отправляю)!

Я добавил «BREAK_POINT» в функцию обратного вызова, но так и не дошел до него. Вы можете мне помочь? либо предлагая решение, либо, по крайней мере, способ отслеживать проблему ... Я использую плату Nucleo STM32F746 с библиотеками LWIP, FreeRTOS, созданными cubeMX.

Спасибо.

‹** Edit >>> После дополнительных исследований я обнаружил, что проблема заключается в приеме многоадресных кадров, которые должны быть включены во время инициализации MAC. Хотя следующий код не сработал для меня, он был полезен другим, так что вот он:

4- в stm32f7xx_hal_eth.c (функция ETH_MACDMAConfig):

macinit.PromiscuousMode = ETH_PROMISCUOUS_MODE_ENABLE;
macinit.MulticastFramesFilter = ETH_MULTICASTFRAMESFILTER_NONE;

person Kalkhouri    schedule 20.05.2018    source источник


Ответы (1)


Мое многоадресное тестирование было успешно завершено с STM32F407 и CubeMX версии 4.25.0.
Вопрос Калкоури оказался полезным. Я делюсь своим рабочим кодом здесь.

Следующий код должен быть включен так же, как это сделал Калхури.

#define LWIP_IGMP 1
macinit.MulticastFramesFilter = ETH_MULTICASTFRAMESFILTER_NONE;
netif->flags |= NETIF_FLAG_IGMP;

Я использовал API сокетов LWIP, а не функцию низкого уровня.

#include "lwip/opt.h"
#include "lwip/dhcp.h"
#include "lwip/netif.h"
#include "lwip/tcpip.h"
#include "lwip/sockets.h"

int Bind(int sock, uint16_t port)
{
  struct sockaddr_in serv_addr;
  serv_addr.sin_family = AF_INET;
  serv_addr.sin_addr.s_addr = INADDR_ANY;
  serv_addr.sin_port = htons(port);
  if (bind(sock, (struct sockaddr *) &serv_addr, (socklen_t)sizeof(serv_addr)) < 0)
    return -1;
  return 0;
}

int JoinGroup(int sock, const char* join_ip, const char* local_ip)
{
  ip_mreq mreq;
  mreq.imr_multiaddr.s_addr = inet_addr(join_ip);
  mreq.imr_interface.s_addr = inet_addr(local_ip);
  if (setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&mreq, sizeof(mreq)) < 0)
    return -1;
  return 0;
}

void  MulticastStart()
{
  int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
  Bind(sock, 5000);
  JoinGroup(sock, "224.1.1.1", "192.168.10.123");

  // Now you can do recvfrom() in RTOS task.
  ........
}

Примечание. Этот код следует использовать при поддержке RTOS.

person Hill    schedule 28.06.2018