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)
|
|