硬汉嵌入式论坛

 找回密码
 立即注册
查看: 3348|回复: 5
收起左侧

[emWin] emwin + lwip 闪屏

[复制链接]

100

主题

94

回帖

394

积分

高级会员

积分
394
发表于 2020-2-20 19:40:16 | 显示全部楼层 |阅读模式
当设备当插上网线时候,启动了网络相关的线程,这时后操作界面,不一定在登陆界面,很多地方都出现闪屏现象,如附件视频。但是一直不插上网线,没有闪屏
static void EmwinTask(void)
{
GUI_Init();       //STemWin初始化
WM_MULTIBUF_Enable(1);    //开启STemWin多缓冲,RGB屏可能会用到
WM_MOTION_Enable(0);
WM_MOTION_SetDefaultPeriod(500);
GUI_UC_SetEncodeUTF8();
....

CreateXXXWindow(WM_HBKWIN);
while(1)
{
  GUI_TOUCH_Exec();   
  GUI_Delay(5);
}
}
void init_network_task(void *pvParameters)
{
int ret;
while(1)
{   
  if(!lwipInitFlag)
  {  
   ret  = lwip_comm_init();
   if(ret)
   {
    lwipInitFlag = 0;
    //初始化失败
   }
   else
   {
    //建立tcp连接
    while(tcp_client_init());
  
    lwip_comm_dhcp_creat(); //创建DHCP任务
    lwipInitFlag=1;
   }
  }
  
  vTaskDelay(100);
}
}

u8 lwip_comm_init(void)
{
  u8 retry=0;
struct netif *Netif_Init_Flag;  //调用netif_add()函数时的返回值,用于判断网络初始化是否成功
struct ip_addr ipaddr;     //ip地址
struct ip_addr netmask;    //子网掩码
struct ip_addr gw;         //默认网关
if(eth_memery_flag==1){
  //内存申请过,没有释放
}else{
   if(ETH_Mem_Malloc())return 1;  //内存申请失败
}
if(lwip_memery_flag==1){
  //申请的内存没有释放
}else{
  if(lwip_comm_mem_malloc())return 2; //内存申请失败
}
    lwip_comm_default_ip_set(&lwipdev); //设置默认IP等信息
while(LAN8720_Init())          //初始化LAN8720
    {
        retry++;
        if(retry>1) {retry=0;return 3;} //LAN8720初始化失败
    }
taskENTER_CRITICAL();           //进入临界区
tcpip_init(NULL,NULL);    //初始化tcp ip内核,该函数里面会创建tcpip_thread内核任务
taskEXIT_CRITICAL();            //退出临界区
#if LWIP_DHCP  //使用动态IP
ipaddr.addr = 0;
netmask.addr = 0;
gw.addr = 0;
#else    //使用静态IP
IP4_ADDR(&ipaddr,lwipdev.ip[0],lwipdev.ip[1],lwipdev.ip[2],lwipdev.ip[3]);
IP4_ADDR(&netmask,lwipdev.netmask[0],lwipdev.netmask[1] ,lwipdev.netmask[2],lwipdev.netmask[3]);
IP4_ADDR(&gw,lwipdev.gateway[0],lwipdev.gateway[1],lwipdev.gateway[2],lwipdev.gateway[3]);
printf("网卡en的MAC地址为:................%d.%d.%d.%d.%d.%d\r\n",lwipdev.mac[0],lwipdev.mac[1],lwipdev.mac[2],lwipdev.mac[3],lwipdev.mac[4],lwipdev.mac[5]);
printf("静态IP地址........................%d.%d.%d.%d\r\n",lwipdev.ip[0],lwipdev.ip[1],lwipdev.ip[2],lwipdev.ip[3]);
printf("子网掩码..........................%d.%d.%d.%d\r\n",lwipdev.netmask[0],lwipdev.netmask[1],lwipdev.netmask[2],lwipdev.netmask[3]);
printf("默认网关..........................%d.%d.%d.%d\r\n",lwipdev.gateway[0],lwipdev.gateway[1],lwipdev.gateway[2],lwipdev.gateway[3]);
#endif
Netif_Init_Flag=netif_add(&lwip_netif,&ipaddr,&netmask,&gw,NULL,&ethernetif_init,&tcpip_input);//向网卡列表中添加一个网口
if(Netif_Init_Flag==NULL)return 4;//网卡添加失败
else//网口添加成功后,设置netif为默认值,并且打开netif网口
{
  netif_set_default(&lwip_netif); //设置netif为默认网口
  netif_set_up(&lwip_netif);  //打开netif网口
}
return 0;//操作OK.
}   
u8 tcp_client_init(void)
{
BaseType_t result;
taskENTER_CRITICAL(); //关中断
//创建TCP客户端线程
result=xTaskCreate((TaskFunction_t )tcp_client_thread,      //任务函数
                (const char*    )"tcp_client_thread",        //任务名称
                (uint16_t       )TCPCLIENT_STK_SIZE,        //任务堆栈大小
                (void*          )NULL,                  //传递给任务函数的参数
                (UBaseType_t    )TCPCLIENT_PRIO,       //任务优先级
                (TaskHandle_t*  )&TcpClentTask_Handler);   //任务句柄      
taskEXIT_CRITICAL();  //开中断
if(result == pdPASS)return 0;
return 1;
}


static void tcp_client_thread(void *arg)
{
u32 data_len = 0;
struct pbuf *q;
err_t err,recv_err;
static ip_addr_t server_ipaddr,loca_ipaddr;
static u16_t    server_port,loca_port;

LWIP_UNUSED_ARG(arg);

//server_port = REMOTE_PORT;
server_port = user_lwip_dev.remotePort;
IP4_ADDR(&server_ipaddr, lwipdev.remoteip[0],lwipdev.remoteip[1], lwipdev.remoteip[2],lwipdev.remoteip[3]);

while (1)
{
  tcp_clientconn = netconn_new(NETCONN_TCP);  //创建一个TCP链接
  err = netconn_connect(tcp_clientconn,&server_ipaddr,server_port);//连接服务器
  if(err != ERR_OK)  netconn_delete(tcp_clientconn); //返回值不等于ERR_OK,删除tcp_clientconn连接
  else if (err == ERR_OK)    //处理新连接的数据
  {
   struct netbuf *recvbuf;
   tcp_clientconn->recv_timeout = 10;
   netconn_getaddr(tcp_clientconn,&loca_ipaddr,&loca_port,1); //获取本地IP主机IP地址和端口号
   printf("连接上服务器%d.%d.%d.%d,本机端口号为:%d\r\n",lwipdev.remoteip[0],lwipdev.remoteip[1], lwipdev.remoteip[2],lwipdev.remoteip[3],loca_port);
   while(1)
   {
    if((recv_err = netconn_recv(tcp_clientconn,&recvbuf)) == ERR_OK)  //接收到数据
    {
     taskENTER_CRITICAL(); //关中断
     memset(tcp_client_recvbuf,0,TCP_CLIENT_RX_BUFSIZE);  //数据接收缓冲区清零
     for(q=recvbuf->p;q!=NULL;q=q->next)  //遍历完整个pbuf链表
     {
      //判断要拷贝到TCP_CLIENT_RX_BUFSIZE中的数据是否大于TCP_CLIENT_RX_BUFSIZE的剩余空间,如果大于
      //的话就只拷贝TCP_CLIENT_RX_BUFSIZE中剩余长度的数据,否则的话就拷贝所有的数据
      if(q->len > (TCP_CLIENT_RX_BUFSIZE-data_len)) memcpy(tcp_client_recvbuf+data_len,q->payload,(TCP_CLIENT_RX_BUFSIZE-data_len));//拷贝数据
      else memcpy(tcp_client_recvbuf+data_len,q->payload,q->len);
      data_len += q->len;
      if(data_len > TCP_CLIENT_RX_BUFSIZE) break; //超出TCP客户端接收数组,跳出
     }
     taskEXIT_CRITICAL();  //开中断
     //处理接收到的数据
     ApiTcpReceiveNetData(tcp_client_recvbuf,data_len);
     data_len=0;  //复制完成后data_len要清零。
     netbuf_delete(recvbuf);
    }else if(recv_err == ERR_CLSD)  //关闭连接
     {
     netconn_close(tcp_clientconn);
     netconn_delete(tcp_clientconn);
     printf("服务器%d.%d.%d.%d断开连接\r\n",lwipdev.remoteip[0],lwipdev.remoteip[1], lwipdev.remoteip[2],lwipdev.remoteip[3]);
     break;
     }
     //获取路由信息
     
   }
  }
}
}


void lwip_comm_dhcp_creat(void)
{
taskENTER_CRITICAL();  //进入临界区
xTaskCreate((TaskFunction_t)lwip_dhcp_task,
      (const char*  )"DHCP_TASK",
      (uint16_t     )LWIP_DHCP_STK_SIZE,
      (void*        )NULL,
      (UBaseType_t  )LWIP_DHCP_TASK_PRIO,
      (TaskHandle_t*)&LWIP_DHCP_TaskHandler);//创建DHCP任务      
taskEXIT_CRITICAL();  //退出临界区
}


void lwip_dhcp_task(void *pdata)
{
u32 ip=0,netmask=0,gw=0;
dhcp_start(&lwip_netif);//开启DHCP
lwipdev.dhcpstatus=0; //正在DHCP
printf("正在查找DHCP服务器,请稍等...........\r\n");   
while(1)
{
  printf("正在获取地址...\r\n");
  ip=lwip_netif.ip_addr.addr;  //读取新IP地址
  netmask=lwip_netif.netmask.addr;//读取子网掩码
  gw=lwip_netif.gw.addr;   //读取默认网关
  if(ip!=0)        //当正确读取到IP地址的时候
  {
   lwipdev.dhcpstatus=2; //DHCP成功
    printf("网卡en的MAC地址为:................%d.%d.%d.%d.%d.%d\r\n",lwipdev.mac[0],lwipdev.mac[1],lwipdev.mac[2],lwipdev.mac[3],lwipdev.mac[4],lwipdev.mac[5]);
   //解析出通过DHCP获取到的IP地址
   lwipdev.ip[3]=(uint8_t)(ip>>24);
   lwipdev.ip[2]=(uint8_t)(ip>>16);
   lwipdev.ip[1]=(uint8_t)(ip>>8);
   lwipdev.ip[0]=(uint8_t)(ip);
   printf("通过DHCP获取到IP地址..............%d.%d.%d.%d\r\n",lwipdev.ip[0],lwipdev.ip[1],lwipdev.ip[2],lwipdev.ip[3]);
   //解析通过DHCP获取到的子网掩码地址
   lwipdev.netmask[3]=(uint8_t)(netmask>>24);
   lwipdev.netmask[2]=(uint8_t)(netmask>>16);
   lwipdev.netmask[1]=(uint8_t)(netmask>>8);
   lwipdev.netmask[0]=(uint8_t)(netmask);
   printf("通过DHCP获取到子网掩码............%d.%d.%d.%d\r\n",lwipdev.netmask[0],lwipdev.netmask[1],lwipdev.netmask[2],lwipdev.netmask[3]);
   //解析出通过DHCP获取到的默认网关
   lwipdev.gateway[3]=(uint8_t)(gw>>24);
   lwipdev.gateway[2]=(uint8_t)(gw>>16);
   lwipdev.gateway[1]=(uint8_t)(gw>>8);
   lwipdev.gateway[0]=(uint8_t)(gw);
   printf("通过DHCP获取到的默认网关..........%d.%d.%d.%d\r\n",lwipdev.gateway[0],lwipdev.gateway[1],lwipdev.gateway[2],lwipdev.gateway[3]);
   dhcpStartFlag=1;
   //初始化成功
   lwipInitFlag=1;
   break;
  }else if(lwip_netif.dhcp->tries>LWIP_MAX_DHCP_TRIES) //通过DHCP服务获取IP地址失败,且超过最大尝试次数
  {  
   lwipdev.dhcpstatus=0XFF;//DHCP失败.
   printf("dhcp init error \r\n");
   dhcpStartFlag=0;
   lwipInitFlag=0;
   //使用静态IP地址
//   IP4_ADDR(&(lwip_netif.ip_addr),lwipdev.ip[0],lwipdev.ip[1],lwipdev.ip[2],lwipdev.ip[3]);
//   IP4_ADDR(&(lwip_netif.netmask),lwipdev.netmask[0],lwipdev.netmask[1],lwipdev.netmask[2],lwipdev.netmask[3]);
//   IP4_ADDR(&(lwip_netif.gw),lwipdev.gateway[0],lwipdev.gateway[1],lwipdev.gateway[2],lwipdev.gateway[3]);
//   printf("DHCP服务超时,使用静态IP地址!\r\n");
//   printf("网卡en的MAC地址为:................%d.%d.%d.%d.%d.%d\r\n",lwipdev.mac[0],lwipdev.mac[1],lwipdev.mac[2],lwipdev.mac[3],lwipdev.mac[4],lwipdev.mac[5]);
//   printf("静态IP地址........................%d.%d.%d.%d\r\n",lwipdev.ip[0],lwipdev.ip[1],lwipdev.ip[2],lwipdev.ip[3]);
//   printf("子网掩码..........................%d.%d.%d.%d\r\n",lwipdev.netmask[0],lwipdev.netmask[1],lwipdev.netmask[2],lwipdev.netmask[3]);
//   printf("默认网关..........................%d.%d.%d.%d\r\n",lwipdev.gateway[0],lwipdev.gateway[1],lwipdev.gateway[2],lwipdev.gateway[3]);
   break;
  }  
  delay_ms(250); //延时250ms
}
lwip_comm_dhcp_delete();//删除DHCP任务
}


82c80da887b789f1c3f870380465519b.mp4

429.16 KB, 下载次数: 3

回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
115787
QQ
发表于 2020-2-21 09:11:19 | 显示全部楼层
程序升级框架有问题,多查查。

建议使用此贴的LwIP方案,无此问题:

LwIP网络教程开始更新,使用MDK的RTE环境开发,配套RTX5和FreeRTOS两个版本,更新至第7章(2019-12-12)
http://www.armbbs.cn/forum.php?m ... 5874&fromuid=58
(出处: 硬汉嵌入式论坛)
回复

使用道具 举报

100

主题

94

回帖

394

积分

高级会员

积分
394
 楼主| 发表于 2020-2-21 09:32:38 | 显示全部楼层
eric2013 发表于 2020-2-21 09:11
程序升级框架有问题,多查查。

建议使用此贴的LwIP方案,无此问题:

为什么会涉及到程序升级框架?不是很理解哦,我只是将设备连到局域网??
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
115787
QQ
发表于 2020-2-21 09:59:35 | 显示全部楼层
wen 发表于 2020-2-21 09:32
为什么会涉及到程序升级框架?不是很理解哦,我只是将设备连到局域网??

从你这段时间问的一批emWin问题来看,emWin本身的运行问题不大,都是些设计方法问题。

但是你本帖首次咨询到含有lwip了,我由此推出,你的程序设计有问题。

你看看我的推理是否合理。
回复

使用道具 举报

100

主题

94

回帖

394

积分

高级会员

积分
394
 楼主| 发表于 2020-2-22 11:08:00 | 显示全部楼层
eric2013 发表于 2020-2-21 09:59
从你这段时间问的一批emWin问题来看,emWin本身的运行问题不大,都是些设计方法问题。

但是你本帖首次 ...

任务名称        运行状态        优先级        剩余堆栈        任务序号
---------------------------------------------
USB_task                   R        2        833        8
IDLE                       R        0        37        2
tcpip_thread               B        31        896        11
StatusBarTask              B        2        67        6
EmwinTask                  B        3        480        5
CommuRsvTask               S        8        752        4
tcp_client_thread          S        2        449        12
Tmr Svc                    S        31        93        3
PRINTER_TASK               S        2        439        9

---------------------------------------------
B : 阻塞, R : 就绪, D : 删除, S : 暂停

经过我的查找发现tcpip_thread 的优先级>EmwinTask,会有闪屏,代码如下:
#ifndef TCPIP_THREAD_PRIO
#define TCPIP_THREAD_PRIO                (configMAX_PRIORITIES - 1)         //定义内核任务的优先级为最高32
#endif

当我把TCPIP_THREAD_PRIO 定义为2(小于EmwinTask),就没有闪屏幕现象。但是我不知道这是为啥?而且我这样改动合适么,会有其他隐患么?

另外我发现不用WM_MULTIBUF_Enable,而是使用WM_SetCreateFlags(WM_CF_MEMDEV),优先级不调整也不会有闪屏现象,也不知道为啥?
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
115787
QQ
发表于 2020-2-22 11:22:53 | 显示全部楼层
wen 发表于 2020-2-22 11:08
任务名称        运行状态        优先级        剩余堆栈        任务序号
---------------------------------------------
USB_tas ...

程序的稳定性,最少先不断电连续测试24小时。

1、如果你的TCP功能比较紧急,长时间的emWin刷新比较影响TCP不能得到有效执行。正常情况下emWin任务的优先级仅需比空闲任务高即可,而其它任务都比它高。
2、多缓冲本身对性能要求比较高,最好用32bit SDRAM,可以适当降低你驱动中LTDC时钟,LTDC和SDRAM所涉及到的GPIO速度等级,还有就是用到PFC软排线一定尽可能的短,方便测试。

使用存储设备能用的话,也行。

另外你这个也没有几个任务,按说调试稳定压力不大,多试试。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2025-5-18 14:50 , Processed in 0.348306 second(s), 27 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表