打印
[AT32F407]

【AT-START-F407测评】+udp通讯测试

[复制链接]
933|4
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
        AT-START-F407板载以太网PHY带RJ45连接器,以太网PHY联杰DM9162NP支持10/100Mbps双速以太网通讯,使用以太网MAC时,JP8连体跳线须选择右测IO端。本次工程是在参考官方提供的FreeRTOS例程上,移植进lwip源码,实现PC端与AT-START-F407建立UDP网络通讯。本来想通过0.96寸OLED屏显示PC端发送过来的数据,但不知道是OLED屏硬件的问题还是AT-START-F407板子设置的问题,硬是没能成功驱动。论坛上有坛友使用AT-START-F407成功驱动OLED屏的,奇怪的是采用仿STM32的代码驱动,初始化GPIO函数中还带有“GPIO_InitStructure.GPIO_MaxSpeed = GPIO_MaxSpeed_10MHz;”,雅特力官方的外设库中并没有所谓的“GPIO_MaxSpeed ”成员参数,也不知道坛友们是如何封装并顺利驱动的。
        移植lwip,首先得进入lwip官网,下载最新的“lwIP 2.1.3 released”版本,网址:https://savannah.nongnu.org/projects/lwip/
        然后参考“at32f403a_407_freertos_demo”工程,将lwip源码加入到工程中,并添加头文件路径。官方提供的“at32f407_emac_iap_demo”可借鉴一下,主要用到开发板上的emac模块驱动,DM9162NP相关PHY底层库函数。
        在主函数中创建四个进程任务,任务优先级都设置成2,多任务并发执行,任务四中的udp接收线程优先级设置成1。部分参考代码如下:
#include "at32f403a_407_board.h"
#include "at32f403a_407_clock.h"
#include "at32_emac.h"
#include "stdio.h"
#include "FreeRTOS.h"
#include "task.h"

extern void tcpip_stack_init(void);
extern void udpecho_init(void);

TaskHandle_t led2_handler;
TaskHandle_t led3_handler;
TaskHandle_t led4_handler;
TaskHandle_t network_handler;

/* led2 task */
void led2_task_function(void *pvParameters);
/* led3 task */
void led3_task_function(void *pvParameters);
/* led4 task */
void led4_task_function(void *pvParameters);
/* AppTaskCreate task */
void AppTaskCreate(void *pvParameters);

int main(void)
{
  nvic_priority_group_config(NVIC_PRIORITY_GROUP_4);
  system_clock_config();
  
  /* init led2*/
  at32_led_init(LED2);
  /* init led3*/
  at32_led_init(LED3);
  /* init led4*/
  at32_led_init(LED4);
  
  /* init usart1 */
  uart_print_init(115200);
  
  /* enter critical */
  taskENTER_CRITICAL();

  /* create led2 task */
  if(xTaskCreate((TaskFunction_t )led2_task_function,     
                 (const char*    )"LED2_task",   
                 (uint16_t       )512,
                 (void*          )NULL,
                 (UBaseType_t    )2,
                 (TaskHandle_t*  )&led2_handler) != pdPASS)
  {
    printf("LED2 task could not be created as there was insufficient heap memory remaining.\r\n");
  }        
  else
  {
    printf("LED2 task was created successfully.\r\n");
  }
          /* create led3 task */
  if(xTaskCreate((TaskFunction_t )led3_task_function,     
                 (const char*    )"LED3_task",   
                 (uint16_t       )512,
                 (void*          )NULL,
                 (UBaseType_t    )2,
                 (TaskHandle_t*  )&led2_handler) != pdPASS)
  {
    printf("LED3 task could not be created as there was insufficient heap memory remaining.\r\n");
  }        
  else
  {
    printf("LED3 task was created successfully.\r\n");
  }
          /* create led4 task */
  if(xTaskCreate((TaskFunction_t )led4_task_function,     
                 (const char*    )"LED4_task",   
                 (uint16_t       )512,
                 (void*          )NULL,
                 (UBaseType_t    )2,
                 (TaskHandle_t*  )&led4_handler) != pdPASS)
  {
    printf("LED4 task could not be created as there was insufficient heap memory remaining.\r\n");
  }        
  else
  {
    printf("LED4 task was created successfully.\r\n");
  }
  if(xTaskCreate((TaskFunction_t )AppTaskCreate,     
                 (const char*    )"AppTaskCreate_task",   
                 (uint16_t       )512,
                 (void*          )NULL,
                 (UBaseType_t    )2,
                 (TaskHandle_t*  )&network_handler) != pdPASS)
  {
    printf("AppTaskCreate task could not be created.\r\n");
  }        
  else
  {
    printf("AppTaskCreate task was created successfully.\r\n");
  }
  
  /* exit critical */            
  taskEXIT_CRITICAL();      
              
  /* start scheduler */            
  vTaskStartScheduler();
  
}

/* led2 task function */
void led2_task_function(void *pvParameters)
{
  while(1)
  {
    at32_led_toggle(LED2);
    vTaskDelay(500);
  }
}

/* led3 task function */
void led3_task_function(void *pvParameters)
{
  while(1)
  {
    at32_led_toggle(LED3);
    vTaskDelay(500);
  }
}
/* led4 task function */
void led4_task_function(void *pvParameters)
{
  while(1)
  {
    at32_led_toggle(LED4);
    vTaskDelay(500);
  }
}
/* AppTaskCreate_task */
void AppTaskCreate(void *pvParameters)
{
  while(emac_system_init() == ERROR);
  tcpip_stack_init();
  udpecho_init();
  while(1)
  {
    vTaskDelay(500);
  }
}
   netconf.c中设置本地ip,这里使用静态分配ip地址,没有使能DHCP功能。
#include "lwip/memp.h"
#include "lwip/tcp.h"
#include "lwip/priv/tcp_priv.h"
#include "lwip/udp.h"
#include "netif/etharp.h"
#include "lwip/dhcp.h"
#include "ethernetif.h"
#include "netconf.h"
#include "stdio.h"
#include "at32_emac.h"

#define MAC_ADDR_LENGTH                  (6)
#define ADDR_LENGTH                      (4)

struct netif netif;
TaskHandle_t link_status_handler;
volatile uint32_t tcp_timer = 0;
volatile uint32_t arp_timer = 0;

static uint8_t mac_address[MAC_ADDR_LENGTH] = {0, 0, 0x44, 0x45, 0x56, 1};
#if LWIP_DHCP
volatile uint32_t dhcp_fine_timer = 0;
volatile uint32_t dhcp_coarse_timer = 0;
#else
static uint8_t local_ip[ADDR_LENGTH]   = {192, 168, 0, 105};
static uint8_t local_gw[ADDR_LENGTH]   = {192, 168, 0, 1};
static uint8_t local_mask[ADDR_LENGTH] = {255, 255, 255, 0};
#endif

void tcpip_stack_init(void)
{
  ip_addr_t ipaddr;
  ip_addr_t netmask;
  ip_addr_t gw;
  
  /* Initializes the dynamic memory heap defined by MEM_SIZE.*/
  mem_init();

  /* Initializes the memory pools defined by MEMP_NUM_x.*/
  memp_init();


#if LWIP_DHCP  //need DHCP server
  ipaddr.addr = 0;
  netmask.addr = 0;
  gw.addr = 0;

#else
  IP4_ADDR(&ipaddr, local_ip[0], local_ip[1], local_ip[2], local_ip[3]);
  IP4_ADDR(&netmask, local_mask[0], local_mask[1], local_mask[2], local_mask[3]);
  IP4_ADDR(&gw, local_gw[0], local_gw[1], local_gw[2], local_gw[3]);
        printf("\r\n");
        printf("local_ip:%d.%d.%d.%d\r\n",local_ip[0], local_ip[1], local_ip[2], local_ip[3]);
        printf("local_mask:%d.%d.%d.%d\r\n",local_mask[0], local_mask[1], local_mask[2], local_mask[3]);
        printf("local_gw:%d.%d.%d.%d\r\n",local_gw[0], local_gw[1], local_gw[2], local_gw[3]);
#endif

  lwip_set_mac_address(mac_address);
if(netif_add(&netif, &ipaddr, &netmask, &gw, NULL, ðernetif_init, &netif_input) == NULL)
  {
    while(1);
  }
  
  /*  Registers the default network interface.*/
  netif_set_default(&netif);

#if LWIP_DHCP
dhcp_start(&netif);
#endif
/*  When the netif is fully configured this function must be called.*/
  netif_set_up(&netif);  
  
  /* Set the link callback function, this function is called on change of link status*/
  netif_set_link_callback(&netif, ethernetif_update_config);
  
  /* Create the Ethernet link handler thread */
  xTaskCreate((TaskFunction_t)ethernetif_set_link, "ethernetif_set_link", 512, &netif, tskIDLE_PRIORITY + 3, &link_status_handler);
}

void lwip_pkt_handle(void)
{
  /* Read a received packet from the Ethernet buffers and send it to the lwIP for handling */
  if(ethernetif_input(&netif) != ERR_OK)
  {
    while(1);
  }
}

void lwip_periodic_handle(volatile uint32_t localtime)
{
  /* TCP periodic process every 250 ms */
  if (localtime - tcp_timer >= TCP_TMR_INTERVAL)
  {
    tcp_timer =  localtime;
    tcp_tmr();
  }
  /* ARP periodic process every 5s */
  if (localtime - arp_timer >= ARP_TMR_INTERVAL)
  {
    arp_timer =  localtime;
    etharp_tmr();
  }

#if LWIP_DHCP
  /* Fine DHCP periodic process every 500ms */
  if (localtime - dhcp_fine_timer >= DHCP_FINE_TIMER_MSECS)
  {
    dhcp_fine_timer =  localtime;
    dhcp_fine_tmr();
  }
  /* DHCP Coarse periodic process every 60s */
  if (localtime - dhcp_coarse_timer >= DHCP_COARSE_TIMER_MSECS)
  {
    dhcp_coarse_timer =  localtime;
    dhcp_coarse_tmr();
  }
#endif
}
#include "lwip/opt.h"

#if LWIP_NETCONN
#include "lwip/api.h"
#include "lwip/sys.h"

#define UDPECHO_THREAD_PRIO          1
#define UDPECHO_STK_SIZE                         256  
TaskHandle_t Udpecho_Handler;

static struct netconn *conn;
static struct netbuf *buf;
static ip_addr_t *addr;
static unsigned short port;
static void udpecho_thread(void *arg)
{
  err_t err, recv_err;

  LWIP_UNUSED_ARG(arg);

  conn = netconn_new(NETCONN_UDP);
        printf("connection create successfully\n");
  if (conn!= NULL)
  {
    err = netconn_bind(conn, IP_ADDR_ANY, 8080);
                printf("bind successfully\n");
    if (err == ERR_OK)
    {
      while (1)
      {
                                printf("Receiving...\n");
        recv_err = netconn_recv(conn, &buf);
                                printf("Received done\n");

        if (recv_err == ERR_OK)
        {
          addr = netbuf_fromaddr(buf);
          port = netbuf_fromport(buf);
          netconn_connect(conn, addr, port);
          buf->addr.addr = 0;
          netconn_send(conn,buf);
          netbuf_delete(buf);
        }
      }
    }
    else
    {
      netconn_delete(conn);
    }
  }
}
void udpecho_init(void)
{
  sys_thread_new("udpecho_thread", udpecho_thread, NULL, UDPECHO_STK_SIZE,UDPECHO_THREAD_PRIO );       
}
#endif /* LWIP_NETCONN */
     编译、下载到开发板中,PC端打开串口调试助手,根据串口输出信息,先在“cmd窗口”中ping一下,看是否能够正常ping通。


      然后在PC端中打开“netassist”网路调试助手,并设置好udp通讯方式,本地主机地址(PC)的ip地址,端口号设置成代码中设定的8080;根据串口打印信息,设置远程主机(AT-START-F407)的ip地址,端口号同样设置成8080。
netassist.zip (548.52 KB)

        开发板上的各个指示灯显示如下:

         一路走来,感觉移植lwip还是需要点耐心的,结合FreeRTOS,需要打开的宏必须得打开,否则会报莫名其妙的error,这里尤其注意在“FreeRTOS.h”的文件中,打开“configUSE_COUNTING_SEMAPHORES”宏。以下附件为工程文件,此次分享就告一段落,咱们后会有期。
FreeRTOS_lwip_project.zip (4.81 MB)

使用特权

评论回复
沙发
updownq| | 2023-1-9 10:42 | 只看该作者
这个udp的速度怎么样              

使用特权

评论回复
板凳
yinwuqing110|  楼主 | 2023-1-9 13:42 | 只看该作者
updownq 发表于 2023-1-9 10:42
这个udp的速度怎么样

挺快的呀,具体数值就没测了

使用特权

评论回复
地板
claretttt| | 2023-1-9 14:43 | 只看该作者
使用的是哪个网络模块?              

使用特权

评论回复
5
yinwuqing110|  楼主 | 2023-1-10 09:29 | 只看该作者
claretttt 发表于 2023-1-9 14:43
使用的是哪个网络模块?

开发板上就有集成的DM9162NP芯片呀

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

94

主题

1005

帖子

6

粉丝