SylixOS,协议栈中函数地址转换

这段代码从网络设备的私有数据结构中获取数据包指针,并解析以太网头部,然后进一步提取IP头部信息。它打印了IP头的各个字段,包括版本、服务类型、总长度、标识、标志、生存时间、协议和源/目的IP地址。
  netprp_t *netprp = (netprp_t *)netdev->priv;
  netprp_eth_t *netprp_eth;
  LW_LIST_LINE *pline;
  char         *data = NULL;
  u16_t         length = p->len;
  int           ret;
  struct ethhdr *eh     = (struct ethhdr *)p->payload;
  struct ip_hdr *iphdr  = (struct ip_hdr *)(p->payload + SIZEOF_ETH_HDR - 2);       // ip 头

//  printk("iphdr : _v_hl = %d \n\r",iphdr->_v_hl);
//  printk("iphdr : _tos  = %d \n\r",iphdr->_tos);
//  printk("iphdr : _len  = %d \n\r",iphdr->_len);
//  printk("iphdr : _id   = %d \n\r",iphdr->_id);
//  printk("iphdr : _offset = %d \n\r",iphdr->_offset);
//  printk("iphdr : _ttl  = %d \n\r",iphdr->_ttl);
//  printk("iphdr : _proto = %d \n\r",iphdr->_proto);
//  printk("iphdr : _chksum = %d \n\r",iphdr->_chksum);
//  printk("iphdr : src   = %s \n\r",ip4addr_ntoa(&iphdr->src.addr));
//  printk("iphdr : dest  = %s \n\r",ip4addr_ntoa(&iphdr->dest.addr));

#define CONN_TASK_STACK_SIZE 384int conn_task_create(void *data, u8 RS485_num, u8 max_conncet, u16 timeout,u8 model) { int i,q; u8 err; void (*task_entryTCP)(void *p_arg); /* 函数指针 */ void (*task_entryRS485)(void *p_arg); /* 函数指针 */ /* 1. 检查是否已达上限 */ if (create_number[RS485_num - 1] >= max_conncet) { return -1; // 返回特殊错误码:达到上限 } /* 从0开始查找网络空闲项 */ for (i = 0; i < MAX_CONN_TASK; i++) { if (task[i].prio == OS_ERR_PRIO_INVALID) { break; } } if (i >= MAX_CONN_TASK) // 没有空闲任务 { return -1; } /* 从0开始查找串口空闲项 */ for (q = 0; q < MAX_UART_TASK; q++) { if (UartTask[q].prio == OS_ERR_PRIO_INVALID) { break; } } if (q >= MAX_UART_TASK) // 没有空闲任务 { return -1; } /* 申请共享结构体 */ TcpServer_pair_t *pair = (TcpServer_pair_t *)mymalloc(SRAMEX, sizeof(TcpServer_pair_t)); if (!pair) return -1; pair->conn = data; pair->exit_flag[0] = 0; pair->exit_flag[1] = 0; pair->ref_count = 2; // 两个线程共享 pair->timeout_ms = timeout; pair->rs485_num = RS485_num; /* 分配栈并创建任务1:TCP→RS485 */ task[i].stk = mymalloc(SRAMEX, CONN_TASK_STACK_SIZE * 4); if (!task[i].stk) goto fail; err = OSTaskCreate(child_task, pair, &task[i].stk[CONN_TASK_STACK_SIZE - 1], CONN_TASK_PRIO_BASE + i); if (err != OS_NO_ERR) goto fail; task[i].prio = CONN_TASK_PRIO_BASE + i; task[i].data = pair; pair->prio0 = CONN_TASK_PRIO_BASE + i; /* 分配栈并创建任务2:RS485→TCP */ UartTask[q].stk = mymalloc(SRAMEX, CONN_TASK_STACK_SIZE * 4); if (!UartTask[q].stk) goto fail; err = OSTaskCreate(TTPchild_task_rs485, pair, &UartTask[q].stk[CONN_TASK_STACK_SIZE - 1], UART_TASK_PRIO_BASE + q); if (err != OS_NO_ERR) goto fail; UartTask[q].prio = UART_TASK_PRIO_BASE + q; UartTask[q].rs485_now = RS485_num; pair->prio1 = UART_TASK_PRIO_BASE + q; /* 4. 成功创建后,增加计数器 */ create_number[RS485_num - 1]++; pair->timenow = sys_now(); // 初始化活动时间 return 0; fail: if (pair) myfree(SRAMEX, pair); if (task[i].stk) myfree(SRAMEX, task[i].stk); if (UartTask[q].stk) myfree(SRAMEX, UartTask[q].stk); return -1; }void child_task(void *arg) { TcpServer_pair_t *pair = (TcpServer_pair_t *)arg; struct netconn *conn = pair->conn; struct netbuf *recvbuf; err_t err; u32_t now; INT8U err1; u8 rs485 = pair->rs485_num - 1; ClientAdd(pair->rs485_num, conn); while (!pair->exit_flag[1]) { err = netconn_recv(conn, &recvbuf); if (err == ERR_OK) { for (struct pbuf *q = recvbuf->p; q != NULL; q = q->next) { u8 dropped = 1; /* 先假定要丢包 */ for(u8 i = 0;i < shengdu;i++) { if(SerialSendCtx[rs485][i].style == 0)//有空闲缓冲区 { if (q->len > SerialSendCtx[rs485][i].len) { /* 缓存太小,直接当作丢包 */ break; } mymemcpy(SerialSendCtx[rs485][i].buf, (u8 *)q->payload, q->len); SerialSendCtx[rs485][i].usedlen = q->len; SerialSendCtx[rs485][i].style = 1; dropped = 0; break; } } if (dropped) /* 10 个槽全忙 */ { dropSend_cnt[rs485]++; } } netbuf_delete(recvbuf); } else if (err == ERR_TIMEOUT) { now = sys_now(); if (now - pair->timenow > pair->timeout_ms) { break; } } else { break; } } /* 通知伙伴线程退出 */ pair->exit_flag[0] = 1; if (--pair->ref_count == 0) { ClientDel(pair->rs485_num, conn); netconn_close(conn); netconn_delete(conn); myfree(SRAMEX, pair); if (create_number > 0) { create_number[pair->rs485_num - 1]--; } } conn_task_del(pair->prio0); }void child_task_rs4851(void *arg) { TcpServer_pair_t *pair = (TcpServer_pair_t *)arg; struct netconn *conn = pair->conn; INT8U err; u8 id; u8 rs485 = pair->rs485_num; id = Getenabled_Server(pair->rs485_num); UART_PORT_CTX_t *ctx = &gUartCtx[id]; while (!pair->exit_flag[0]) { FRAME *pf = (FRAME *)OSQPend(ctx->broadQ, 100, &err); // 等待本串口广播 if (err == OS_TIMEOUT) continue; if (!pf) continue; if(pf->usedlen == 0 || pf->usedlen > 1024) { if (--pf->ref == 0) { OSFlagPost(FlagSendGrp[rs485 - 1], FLAG_TX_DONE, OS_FLAG_SET, &err);// bit0置位 } continue;// 转换失败,跳过 } else { if (netconn_write(conn, pf->buf, pf->usedlen, NETCONN_COPY) == ERR_OK) { pair->timenow = sys_now(); /* 释放动态内存 */ if (--pf->ref == 0) { OSFlagPost(FlagSendGrp[rs485 - 1], FLAG_TX_DONE, OS_FLAG_SET, &err);// bit0置位 } } else { break; } } OSTimeDlyHMSM(0, 0, 0, 10); // 延时5ms } /* 通知伙伴线程退出 */ pair->exit_flag[1] = 1; if (--pair->ref_count == 0) { ClientDel(pair->rs485_num, conn); netconn_close(conn); netconn_delete(conn); myfree(SRAMEX, pair); if (create_number > 0) { create_number[pair->rs485_num - 1]--; } } conn_task_del(pair->prio1); // 收回该线程 } 最终发现如果注释掉这个任务创建 err = OSTaskCreate(TTPchild_task_rs485, pair, &UartTask[q].stk[CONN_TASK_STACK_SIZE - 1], UART_TASK_PRIO_BASE + q); if (err != OS_NO_ERR) goto fail; UartTask[q].prio = UART_TASK_PRIO_BASE + q; UartTask[q].rs485_now = RS485_num; pair->prio1 = UART_TASK_PRIO_BASE + q;时可以实现24个客户端不崩溃但是如果不注释的话到第15个客户端就会奔溃但是我这俩个批量创建的任务已经经过了14个客户端读写的长期稳定性测试了啊代码逻辑应该没有问题为什么会出现第15个客户端连接后读写触发硬件复位回溯最后执行在etharp_update_arp_entry(struct netif *netif, ip_addr_t *ipaddr, struct eth_addr *ethaddr, u8_t flags) { s8_t i; LWIP_ASSERT("netif->hwaddr_len == ETHARP_HWADDR_LEN", netif->hwaddr_len == ETHARP_HWADDR_LEN); LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_update_arp_entry: %"U16_F".%"U16_F".%"U16_F".%"U16_F" - %02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F"\n", ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr), ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr), ethaddr->addr[0], ethaddr->addr[1], ethaddr->addr[2], ethaddr->addr[3], ethaddr->addr[4], ethaddr->addr[5])); /* non-unicast address? */ if (ip_addr_isany(ipaddr) || ip_addr_isbroadcast(ipaddr, netif) || ip_addr_ismulticast(ipaddr)) { LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_update_arp_entry: will not add non-unicast IP address to ARP cache\n")); return ERR_ARG; } /* find or create ARP entry */ i = etharp_find_entry(ipaddr, flags); /* bail out if no entry could be found */ if (i < 0) { return (err_t)i; } #if ETHARP_SUPPORT_STATIC_ENTRIES if (flags & ETHARP_FLAG_STATIC_ENTRY) { /* record static type */ arp_table[i].state = ETHARP_STATE_STATIC; } else #endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ { /* mark it stable */ arp_table[i].state = ETHARP_STATE_STABLE; } /* record network interface */ arp_table[i].netif = netif; /* insert in SNMP ARP index tree */ snmp_insert_arpidx_tree(netif, &arp_table[i].ipaddr); LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_update_arp_entry: updating stable entry %"S16_F"\n", (s16_t)i)); /* update address */ ETHADDR32_COPY(&arp_table[i].ethaddr, ethaddr); /* reset time stamp */ arp_table[i].ctime = 0; /* this is where we will send out queued packets! */ #if ARP_QUEUEING while (arp_table[i].q != NULL) { struct pbuf *p; /* remember remainder of queue */ struct etharp_q_entry *q = arp_table[i].q; /* pop first item off the queue */ arp_table[i].q = q->next; /* get the packet pointer */ p = q->p; /* now queue entry can be freed */ memp_free(MEMP_ARP_QUEUE, q); #else /* ARP_QUEUEING */ if (arp_table[i].q != NULL) { struct pbuf *p = arp_table[i].q; arp_table[i].q = NULL; #endif /* ARP_QUEUEING */ /* send the queued IP packet */ etharp_send_ip(netif, p, (struct eth_addr*)(netif->hwaddr), ethaddr); /* free the queued IP packet */ pbuf_free(p); } return ERR_OK; }中的 pbuf_free(p);呢同时我也试过把TTPchild_task_rs485 中的所有逻辑都注释掉只剩下一个循环和让出时间片依然到15个客户端触发这个错误
10-12
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值