yinwuqing110 发表于 2023-1-8 20:46

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

      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 = {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   = {192, 168, 0, 105};
static uint8_t local_gw   = {192, 168, 0, 1};
static uint8_t local_mask = {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, local_ip, local_ip, local_ip);
IP4_ADDR(&netmask, local_mask, local_mask, local_mask, local_mask);
IP4_ADDR(&gw, local_gw, local_gw, local_gw, local_gw);
        printf("\r\n");
        printf("local_ip:%d.%d.%d.%d\r\n",local_ip, local_ip, local_ip, local_ip);
        printf("local_mask:%d.%d.%d.%d\r\n",local_mask, local_mask, local_mask, local_mask);
        printf("local_gw:%d.%d.%d.%d\r\n",local_gw, local_gw, local_gw, local_gw);
#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。


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

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

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

使用的是哪个网络模块?            

yinwuqing110 发表于 2023-1-10 09:29

claretttt 发表于 2023-1-9 14:43
使用的是哪个网络模块?

开发板上就有集成的DM9162NP芯片呀
页: [1]
查看完整版本: 【AT-START-F407测评】+udp通讯测试