RM新时代网站-首页

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

RT-Thread源碼分析之網(wǎng)卡數(shù)據(jù)的接收和發(fā)送

冬至子 ? 來(lái)源:happycode999 ? 作者:happycode999 ? 2023-08-11 16:49 ? 次閱讀

一、lwip網(wǎng)卡接口ethernetif.c
ethernetif.c是lwip的網(wǎng)卡接口,在該接口中處理網(wǎng)卡的數(shù)據(jù)接收和發(fā)送,rt-thread在該接口文件中抽象了一個(gè)eth_device,管理網(wǎng)絡(luò)數(shù)據(jù)的收發(fā)和向內(nèi)核的netdev_list添加netdev。

二、網(wǎng)絡(luò)設(shè)備eth_device
eth_device是rt-thread實(shí)現(xiàn)的ethernetif。

struct eth_device
{
/* inherit from rt_device /
struct rt_device parent;
/
network interface for lwip */
struct netif netif;
struct rt_semaphore tx_ack;
rt_uint16_t flags;
rt_uint8_t link_changed;
rt_uint8_t link_status;
/
eth device interface /
struct pbuf
(*eth_rx)(rt_device_t dev);
rt_err_t (eth_tx)(rt_device_t dev, struct pbuf p);
};
netif:lwip的網(wǎng)絡(luò)接口。
eth_rx:底層數(shù)據(jù)接收接口。
eth_tx:底層數(shù)據(jù)發(fā)送接口。

三、網(wǎng)絡(luò)設(shè)備數(shù)據(jù)的接收和發(fā)送
網(wǎng)絡(luò)設(shè)備的接收和發(fā)送通過(guò)eth_device的eth_rx和eth_tx完成。在系統(tǒng)初始化時(shí)內(nèi)核調(diào)用eth_system_device_init創(chuàng)建erx和etx兩個(gè)線程,用于處理接收和發(fā)送。

3.1 數(shù)據(jù)接收
當(dāng)erx線程起來(lái)后,等待eth_rx_thread_mb,當(dāng)網(wǎng)卡準(zhǔn)備好或者改變網(wǎng)卡狀態(tài)時(shí),往下執(zhí)行,進(jìn)入while(1)處理網(wǎng)卡接收,調(diào)用網(wǎng)卡注冊(cè)的eth_rx接收網(wǎng)卡數(shù)據(jù),并傳遞給協(xié)議棧上層。

static void eth_rx_thread_entry(void* parameter)
{
struct eth_device* device;
while (1)
{
if (rt_mb_recv(e_rx_thread_mb, (rt_ubase_t*)&device, RT_WAITING_FOREVER) == RT_EOK)
{
struct pbuf p;
/
check link status /
if (device->link_changed)
{
int status;
rt_uint32_t level;
level = rt_hw_interrupt_disable();
status = device->link_status;
device->link_changed = 0x00;
rt_hw_interrupt_enable(level);
if (status)
netifapi_netif_set_link_up(device->netif);
else
netifapi_netif_set_link_down(device->netif);
}
/
receive all of buffer /
while (1)
{
if(device->eth_rx == RT_NULL) break;
p = device->eth_rx(&(device->parent));
if (p != RT_NULL)
{
/
notify to upper layer */
if( device->netif->input(p, device->netif) != ERR_OK )
{
LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: Input errorn"));
pbuf_free(p);
p = NULL;
}
}
else break;
}
}
else
{
LWIP_ASSERT("Should not happen!n",0);
}
}
}
3.2 數(shù)據(jù)發(fā)送
當(dāng)協(xié)議棧需要發(fā)送數(shù)據(jù)時(shí),調(diào)用netif的linkoutput接口,在linkoutput中,將數(shù)據(jù)封裝成消息發(fā)送給etx線程,最終通過(guò)eth_device的eth_tx接口將數(shù)據(jù)發(fā)送出去。

static void eth_tx_thread_entry(void* parameter)
{
struct eth_tx_msg* msg;
while (1)
{
if (rt_mb_recv(e_tx_thread_mb, (rt_ubase_t*)&msg, RT_WAITING_FOREVER) == RT_EOK)
{
struct eth_device* enetif;
RT_ASSERT(msg->netif != RT_NULL);
RT_ASSERT(msg->buf != RT_NULL);
enetif = (struct eth_device*)msg->netif->state;
if (enetif != RT_NULL)
{
/* call driver's interface /
if (enetif->eth_tx(&(enetif->parent), msg->buf) != RT_EOK)
{
/
transmit eth packet failed /
}
}
/
send ACK */
rt_sem_release(&(enetif->tx_ack));
}
}
}

四、wlan設(shè)備數(shù)據(jù)的接收和發(fā)送
wlan設(shè)備的數(shù)據(jù)接收和發(fā)送是通過(guò)rt_wlan_prot完成的,rt_wlan_prot是對(duì)不同協(xié)議簇的抽象,在rt_wlan_set_mode啟動(dòng)wlan設(shè)備時(shí),最終會(huì)調(diào)用rt_wlan_prot_attach將lwip協(xié)議簇掛載到wlan設(shè)備,在掛載過(guò)程中,會(huì)根據(jù)協(xié)議簇的名稱匹配注冊(cè)的rt_wlan_prot,并調(diào)用rt_wlan_prot的register將wlan設(shè)備注冊(cè)到內(nèi)核。

4.1 數(shù)據(jù)接收
在網(wǎng)卡的接收中斷中,調(diào)用rt_wlan_dev_transfer_prot將網(wǎng)卡設(shè)備接收的數(shù)據(jù)傳遞給上層處理。

rt_err_t rt_wlan_dev_transfer_prot(struct rt_wlan_device *wlan, void *buff, int len)
{
struct rt_wlan_prot *prot = wlan->prot;
if (prot != RT_NULL)
{
return prot->ops->prot_recv(wlan, buff, len);
}
return -RT_ERROR;
}
注冊(cè)到rt_wlan_prot的接收函數(shù)是rt_wlan_lwip_protocol_recv,在rt_wlan_lwip_protocol_recv中,通過(guò)lwip_prot_des獲取eth_device(netif在eth_device_init_with_flag中被注冊(cè)到eth_device),接著便可使用其中的netif的input將數(shù)據(jù)交給上層。

static rt_err_t rt_wlan_lwip_protocol_recv(struct rt_wlan_device *wlan, void *buff, int len)
{
struct eth_device *eth_dev = &((struct lwip_prot_des *)wlan->prot)->eth;//eth在rt_wlan_lwip_protocol_register中注冊(cè)
struct pbuf *p = RT_NULL;
//...省略
{
p = buff;
if ((eth_dev->netif->input(p, eth_dev->netif)) != ERR_OK)
{
return -RT_ERROR;
}
return RT_EOK;
}
//...省略
}

4.2 數(shù)據(jù)發(fā)送
當(dāng)協(xié)議棧需要發(fā)送數(shù)據(jù)時(shí),會(huì)調(diào)用rt_wlan_prot_transfer_dev將數(shù)據(jù)傳遞給wlan設(shè)備,在rt_wlan_prot_transfer_dev中,會(huì)調(diào)用wlan設(shè)備的發(fā)送接口將數(shù)據(jù)發(fā)送出去。

4.3 以w601舉例
w601的wlan驅(qū)動(dòng)在driver文件夾下的drv_wifi.c。

4.3.1 數(shù)據(jù)接收
在內(nèi)核需要初始化wlan的時(shí)候,調(diào)用drv_wlan_init,在tls_ethernet_data_rx_callback函數(shù)中注冊(cè)wm_ethernetif_input到wifi接收中斷,在wm_ethernetif_input中調(diào)用rt_wlan_dev_transfer_prot將接收的數(shù)據(jù)傳給協(xié)議棧上層。

4.3.2 數(shù)據(jù)發(fā)送
在drv_wifi.c中,將drv_wlan_send函數(shù)注冊(cè)到發(fā)送接口,在協(xié)議棧需要發(fā)送數(shù)據(jù)時(shí),通過(guò)rt_wlan_prot_transfer_dev調(diào)用這個(gè)接口完成數(shù)據(jù)的發(fā)送。

static const struct rt_wlan_dev_ops ops =
{
//...省略
.wlan_recv = drv_wlan_recv,
.wlan_send = drv_wlan_send,/ 向內(nèi)核注冊(cè)的發(fā)送接口 /
};

聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 接收機(jī)
    +關(guān)注

    關(guān)注

    8

    文章

    1180

    瀏覽量

    53453
  • WLAN技術(shù)
    +關(guān)注

    關(guān)注

    0

    文章

    23

    瀏覽量

    9273
  • LwIP協(xié)議
    +關(guān)注

    關(guān)注

    0

    文章

    11

    瀏覽量

    8911
  • 串口中斷
    +關(guān)注

    關(guān)注

    0

    文章

    64

    瀏覽量

    13882
  • RT-Thread
    +關(guān)注

    關(guān)注

    31

    文章

    1285

    瀏覽量

    40081
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    RT-Thread記錄(十一、UART設(shè)備—源碼解析)

    一文帶你深入理解 RT-Thread I/O 設(shè)備模型 — UART 設(shè)備源碼分析
    的頭像 發(fā)表于 07-01 11:24 ?5466次閱讀
    <b class='flag-5'>RT-Thread</b>記錄(十一、UART設(shè)備—<b class='flag-5'>源碼</b>解析)

    RT-thread源碼移植到STM32F10x和STM32F4xx

    RT-thread源碼移植到STM32F10x和STM32F4xx: 一、源碼下載 點(diǎn)擊入門(mén)->下載 ? 在歷史版本里邊隨便選取一個(gè) ? 會(huì)進(jìn)入百度云盤(pán)的下載地址,里邊有全部版本的源碼
    的頭像 發(fā)表于 11-15 09:38 ?2552次閱讀
    <b class='flag-5'>RT-thread</b><b class='flag-5'>源碼</b>移植到STM32F10x和STM32F4xx

    RT-Thread Nano入門(mén):串口接收與消息隊(duì)列

    本文主要介紹怎么用RT-Thread Nano的消息隊(duì)列方式實(shí)現(xiàn)串口數(shù)據(jù)接收,結(jié)合串口接收中斷和空閑中斷,接收上位機(jī)發(fā)來(lái)的一幀
    的頭像 發(fā)表于 11-22 11:07 ?4205次閱讀
    <b class='flag-5'>RT-Thread</b> Nano入門(mén):串口<b class='flag-5'>接收</b>與消息隊(duì)列

    如何使用RT-Thread的串口設(shè)備

    。進(jìn)階閱讀串口通常被配置為接收中斷和輪詢發(fā)送模式。在中斷模式下,CPU 不需要一直查詢等待串口相關(guān)標(biāo)志寄存器,串口接收數(shù)據(jù)后觸發(fā)中斷,我們?cè)谥袛喾?wù)程序進(jìn)行
    發(fā)表于 10-25 11:05

    RT-Thread編程指南

    RT-Thread編程指南——RT-Thread開(kāi)發(fā)組(2015-03-31)。RT-Thread做為國(guó)內(nèi)有較大影響力的開(kāi)源實(shí)時(shí)操作系統(tǒng),本文是RT-Thread實(shí)時(shí)操作系統(tǒng)的編程指南
    發(fā)表于 11-26 16:06 ?0次下載

    基于RT-Thread的FM1702源碼

    RT-Thread是一款來(lái)自中國(guó)的開(kāi)源嵌入式實(shí)時(shí)操作系統(tǒng),包括一系列應(yīng)用組件和驅(qū)動(dòng)框架,如TCP/IP協(xié)議棧,虛擬文件系統(tǒng),POSIX接口,圖形用戶界面。---(轉(zhuǎn)自RTT官網(wǎng))。 FM1702是無(wú)線射頻的一種,現(xiàn)將其移植到RT-Thread操作系統(tǒng)中。
    發(fā)表于 12-28 10:54 ?15次下載

    RT-Thread Studio驅(qū)動(dòng)SD卡

    RT-Thread Studio驅(qū)動(dòng)SD卡前言一、創(chuàng)建基本工程1、創(chuàng)建Bootloader2、創(chuàng)建項(xiàng)目工程二、配置RT-Thread Settings三、代碼分析1.引入庫(kù)2.讀入數(shù)據(jù)
    發(fā)表于 12-27 19:13 ?20次下載
    <b class='flag-5'>RT-Thread</b> Studio驅(qū)動(dòng)SD卡

    HC32F460移植RT-Thread Nano+FinSh工程源碼下載

    HC32F460移植RT-Thread Nano+FinSh工程源碼下載
    發(fā)表于 01-05 10:30 ?6次下載

    RT-Thread全球技術(shù)大會(huì):RT-Thread測(cè)試用例集合案例

    RT-Thread全球技術(shù)大會(huì):RT-Thread測(cè)試用例集合案例 ? ? ? ? ? 審核編輯:彭靜
    的頭像 發(fā)表于 05-27 16:34 ?2095次閱讀
    <b class='flag-5'>RT-Thread</b>全球技術(shù)大會(huì):<b class='flag-5'>RT-Thread</b>測(cè)試用例集合案例

    RT-Thread學(xué)習(xí)筆記 RT-Thread的架構(gòu)概述

    RT-Thread 簡(jiǎn)介 作為一名 RTOS 的初學(xué)者,也許你對(duì) RT-Thread 還比較陌生。然而,隨著你的深入接觸,你會(huì)逐漸發(fā)現(xiàn) RT-Thread 的魅力和它相較于其他同類型 RTOS
    的頭像 發(fā)表于 07-09 11:27 ?4545次閱讀
    <b class='flag-5'>RT-Thread</b>學(xué)習(xí)筆記 <b class='flag-5'>RT-Thread</b>的架構(gòu)概述

    RT-Thread文檔_RT-Thread 簡(jiǎn)介

    RT-Thread文檔_RT-Thread 簡(jiǎn)介
    發(fā)表于 02-22 18:22 ?5次下載
    <b class='flag-5'>RT-Thread</b>文檔_<b class='flag-5'>RT-Thread</b> 簡(jiǎn)介

    RT-Thread文檔_RT-Thread 潘多拉 STM32L475 上手指南

    RT-Thread文檔_RT-Thread 潘多拉 STM32L475 上手指南
    發(fā)表于 02-22 18:23 ?9次下載
    <b class='flag-5'>RT-Thread</b>文檔_<b class='flag-5'>RT-Thread</b> 潘多拉 STM32L475 上手指南

    RT-Thread文檔_RT-Thread SMP 介紹與移植

    RT-Thread文檔_RT-Thread SMP 介紹與移植
    發(fā)表于 02-22 18:31 ?9次下載
    <b class='flag-5'>RT-Thread</b>文檔_<b class='flag-5'>RT-Thread</b> SMP 介紹與移植

    基于RT-Thread Studio學(xué)習(xí)

    前期準(zhǔn)備:從官網(wǎng)下載 RT-Thread Studio,弄個(gè)賬號(hào)登陸,開(kāi)啟rt-thread學(xué)習(xí)之旅。
    的頭像 發(fā)表于 05-15 11:00 ?3930次閱讀
    基于<b class='flag-5'>RT-Thread</b> Studio學(xué)習(xí)

    rt-thread源碼分析socket抽象層和網(wǎng)卡注冊(cè)

    如圖所示,rt-thread的網(wǎng)絡(luò)分為應(yīng)用層、sal_socket、netdev、協(xié)議簇(at、lwip、wiznet)、網(wǎng)卡驅(qū)動(dòng)五層。
    的頭像 發(fā)表于 11-13 12:43 ?864次閱讀
    RM新时代网站-首页