国产精品久久久久影院,成人午夜福利视频,国产精品久久久久高潮,国产精品 欧美 亚洲 制服,国产精品白浆无码流出

歷史上的今天

今天是:2025年07月15日(星期二)

2019年07月15日 | STM32開發(fā)筆記53:STM32F4+DP83848以太網(wǎng)通信指南系列(七)

發(fā)布者:會哭的藍(lán)精靈 來源: eefocus關(guān)鍵字:STM32  STM32F4  DP83848  以太網(wǎng)通信  發(fā)包流程 手機(jī)看文章 掃描二維碼
隨時(shí)隨地手機(jī)看文章

本章為系列指南的第七章,講述如何在之前的基礎(chǔ)上,編寫程序在STM32上發(fā)送一個(gè)網(wǎng)絡(luò)包,并使用WireShark進(jìn)行驗(yàn)證。

先回顧一下之前的章節(jié)我們做好的準(zhǔn)備工作,在《STM32F4+DP83848以太網(wǎng)通信指南第五章:MAC+DMA配置》結(jié)束時(shí)我們封裝了一個(gè)DP83848的初始化函數(shù),該函數(shù)完成了PHY的配置,MAC層的配置,DMA的配置,并且啟用了以太網(wǎng)中斷,函數(shù)命名為DP83848Init(),那么今天,我們要做的主要任務(wù)就是編寫一個(gè)類似的DP83848Send(u8* data, u16 length)函數(shù)。

可以在本章的一開始跟大家劇透一個(gè)好消息,有了《STM32F4+DP83848以太網(wǎng)通信指南第四章:PHY配置》 和 《STM32F4+DP83848以太網(wǎng)通信指南第五章:MAC+DMA配置》 的基礎(chǔ),我們本章最終實(shí)現(xiàn)的DP83848Send(u8* data, u16 length)函數(shù),只有兩行代碼,非常非常簡單。這兩行代碼我暫時(shí)先不貼出來,我們來順著原來的思路,根據(jù)相關(guān)文檔和官方示例代碼,順藤摸瓜,一步一步深入了解以太網(wǎng)發(fā)包的流程,最終理解體系結(jié)構(gòu)后,也就水到渠成能夠?qū)懗鰜砹恕?p>在 《STM32F4+DP83848以太網(wǎng)通信指南第五章:MAC+DMA配置》 最后一部分提到在LWIP官方樣例中,路徑為STM32F4x7_ETH_LwIP_V1.1.1UtilitiesThird_Partylwip-1.4.1portSTM32F4x7Standaloneethernetif.c的文件中,第76行有個(gè)low_level_init()函數(shù),該函數(shù)調(diào)用ETH庫函數(shù)對MAC底層及DMA進(jìn)行了初始化。同樣的,這份文件的138行,有個(gè)名為low_level_output(struct netif *netif, struct pbuf *p)的函數(shù),疑似是向外輸出網(wǎng)絡(luò)包的函數(shù),下面就對這部分代碼進(jìn)行分析,并試著用其中的核心邏輯進(jìn)行測試。

因?yàn)閑thernetif.c這份代碼本身隸屬于LWIP,而我們是不使用LWIP的,所以這份代碼只能盡量去看懂和借鑒,想要原封不動(dòng)地使用是不可以的。

我們先完整地貼出這個(gè)函數(shù):


/**

 * This function should do the actual transmission of the packet. The packet is

 * contained in the pbuf that is passed to the function. This pbuf

 * might be chained.

 *

 * @param netif the lwip network interface structure for this ethernetif

 * @param p the MAC packet to send (e.g. IP packet including MAC addresses and type)

 * @return ERR_OK if the packet could be sent

 *         an err_t value if the packet couldn't be sent

 *

 * @note Returning ERR_MEM here if a DMA queue of your MAC is full can lead to

 *       strange results. You might consider waiting for space in the DMA queue

 *       to become availale since the stack doesn't retry to send a packet

 *       dropped because of memory failure (except for the TCP timers).

 */

 

static err_t low_level_output(struct netif *netif, struct pbuf *p) {

    err_t errval;

    struct pbuf *q;

    u8 *buffer =  (u8 *)(DMATxDescToSet->Buffer1Addr);

    __IO ETH_DMADESCTypeDef *DmaTxDesc;

    uint16_t framelength = 0;

    uint32_t bufferoffset = 0;

    uint32_t byteslefttocopy = 0;

    uint32_t payloadoffset = 0;

 

    DmaTxDesc = DMATxDescToSet;

    bufferoffset = 0;

 

    /* copy frame from pbufs to driver buffers */

    for(q = p; q != NULL; q = q->next) {

        /* Is this buffer available? If not, goto error */

        if((DmaTxDesc->Status & ETH_DMATxDesc_OWN) != (u32)RESET) {

            errval = ERR_BUF;

            goto error;

        }

 

        /* Get bytes in current lwIP buffer */

        byteslefttocopy = q->len;

        payloadoffset = 0;

 

        /* Check if the length of data to copy is bigger than Tx buffer size*/

        while( (byteslefttocopy + bufferoffset) > ETH_TX_BUF_SIZE ) {

            /* Copy data to Tx buffer*/

            memcpy( (u8_t *)((u8_t *)buffer + bufferoffset), (u8_t *)((u8_t *)q->payload + payloadoffset), (ETH_TX_BUF_SIZE - bufferoffset) );

 

            /* Point to next descriptor */

            DmaTxDesc = (ETH_DMADESCTypeDef *)(DmaTxDesc->Buffer2NextDescAddr);

 

            /* Check if the buffer is available */

            if((DmaTxDesc->Status & ETH_DMATxDesc_OWN) != (u32)RESET) {

                errval = ERR_USE;

                goto error;

            }

 

            buffer = (u8 *)(DmaTxDesc->Buffer1Addr);

 

            byteslefttocopy = byteslefttocopy - (ETH_TX_BUF_SIZE - bufferoffset);

            payloadoffset = payloadoffset + (ETH_TX_BUF_SIZE - bufferoffset);

            framelength = framelength + (ETH_TX_BUF_SIZE - bufferoffset);

            bufferoffset = 0;

        }

 

        /* Copy the remaining bytes */

        memcpy( (u8_t *)((u8_t *)buffer + bufferoffset), (u8_t *)((u8_t *)q->payload + payloadoffset), byteslefttocopy );

        bufferoffset = bufferoffset + byteslefttocopy;

        framelength = framelength + byteslefttocopy;

    }

 

    /* Note: padding and CRC for transmitted frame

       are automatically inserted by DMA */

 

    /* Prepare transmit descriptors to give to DMA*/

    ETH_Prepare_Transmit_Descriptors(framelength);

 

    errval = ERR_OK;

 

error:

 

    /* When Transmit Underflow flag is set, clear it and issue a Transmit Poll Demand to resume transmission */

    if ((ETH->DMASR & ETH_DMASR_TUS) != (uint32_t)RESET) {

        /* Clear TUS ETHERNET DMA flag */

        ETH->DMASR = ETH_DMASR_TUS;

 

        /* Resume DMA transmission*/

        ETH->DMATPDR = 0;

    }

    return errval;

}

這個(gè)函數(shù)的官方注釋描述的就是用來向外發(fā)送以太網(wǎng)包的,函數(shù)中說要發(fā)的包在第二個(gè)參數(shù),類型為pbuf結(jié)構(gòu)體指針的參數(shù)p中,并且說了p可能是個(gè)鏈表,我們看到函數(shù)的兩個(gè)入?yún)⒍际墙Y(jié)構(gòu)體參數(shù),這兩個(gè)結(jié)構(gòu)體的定義我們不需要管,是LWIP自己封裝的一個(gè)結(jié)構(gòu)體。我們?nèi)ほE參數(shù)p的用法,在代碼片段的30行,使用q變量和for循環(huán)遍歷p,因此我們能夠確定p就是個(gè)頭尾相接的pbuf鏈表。繼續(xù)觀察遍歷體中的操作邏輯,我們看到整個(gè)for循環(huán)的主要目的就是在嘗試將q->payload中的byte,利用函數(shù)memcopy()向buffer變量中堆,并且做了一些長度的校驗(yàn),我們繼而去觀察一下buffer變量的定義,第19行的u8 *buffer = (u8 *)(DMATxDescToSet->Buffer1Addr);是一個(gè)比較重要的線索,由此我們可以抽絲剝繭出整體的邏輯,應(yīng)該就是將首尾相接的p遍歷出來,取其中每個(gè)元素的payload區(qū)域,向DMATxDescToSet->Buffer1Addr中壓。最后,第73行的ETH_Prepare_Transmit_Descriptors(framelength);調(diào)用了ETH庫中的函數(shù),實(shí)現(xiàn)了最終的結(jié)局,將網(wǎng)絡(luò)包發(fā)出去,入?yún)⒌膄ramelength應(yīng)該就是需要發(fā)出去的包長度,包內(nèi)容應(yīng)該就是通過DMA技術(shù),將內(nèi)存中的DMATxDescToSet->Buffer1Addr發(fā)出去了。

有了以上針對low_level_output()函數(shù)的分析,我們來做實(shí)驗(yàn)印證一下,因?yàn)槲覀儚牧汩_始構(gòu)建的項(xiàng)目沒有LWIP,也沒有ethernetif.c,更沒有l(wèi)ow_level_output()函數(shù),因此,函數(shù)內(nèi)部的邏輯都需要我們自己手動(dòng)實(shí)現(xiàn),慢著,不要一看到「手動(dòng)實(shí)現(xiàn)」就頭疼,你以為手動(dòng)實(shí)現(xiàn)就很復(fù)雜嗎?不,LWIP把事情搞復(fù)雜了,又是pbuf又是鏈表的,還有長度判斷導(dǎo)致的Buffer2NextDescAddr切換(詳見第43-62行一整段,不過不重要),如果我們手動(dòng)寫這段邏輯,放棄一些異常處理,再放棄那些跟LWIP強(qiáng)相關(guān)的結(jié)構(gòu)體,我們整個(gè)發(fā)包函數(shù)只要兩行就行:

void DP83848Send(u8* data, u16 length){

    memcpy((u8 *)DMATxDescToSet->Buffer1Addr, data, length);

 

    /* Prepare transmit descriptors to give to DMA*/

    ETH_Prepare_Transmit_Descriptors(length);

}

這里附帶說明一下,并不是LWIP原版代碼又臭又長,LWIP要做一個(gè)TCP/IP全棧協(xié)議,還要考慮包長度溢出的眾多問題,我們精簡版的協(xié)議很多不需要考慮,因此可以放棄很多繁瑣的操作。

有了上述DP83848Send()函數(shù),下面來做個(gè)小程序試驗(yàn)一下:

int main() {

    u8 MyMacAddr[6] = {0x08, 0x00, 0x06, 0x00, 0x00, 0x09};

    /* 下面是一段60byte大小的ARP報(bào)文,手動(dòng)構(gòu)建的 */

    u8 mydata[60] = {    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,

                     0x00, 0x01, 0x08, 0x06, 0x00, 0x01, 0x08, 0x00, 0x06, 0x04,

                     0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xc0, 0xa8,

                     0x02, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xa8,

                     0x02, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

                     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

    u32 clock;

 

    /* 默認(rèn)調(diào)用SystemInit,系統(tǒng)時(shí)鐘168MHz */

    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);        //4位搶占,0位響應(yīng)

 

    DP83848Init(MyMacAddr);

 

    while(1){

        DP83848Send(mydata, 60);

 

        clock = 42000000;    //1s延時(shí),while中每個(gè)步進(jìn)需要4個(gè)周期

        while(clock--);

    }

 

}

使用Keil編譯,用JLink下載到STM32F407中,給開發(fā)板接上網(wǎng)線,用WireShark就可以在網(wǎng)口中觀察到STM32每隔1秒鐘向外發(fā)送ARP報(bào)文了,雖然這段報(bào)文幾乎沒有任何意義。

我使用WireShark截圖如下:

總結(jié)一下,這一章我們完成了一個(gè)DP83848Send()發(fā)包函數(shù),這個(gè)函數(shù)可以接受一個(gè)字節(jié)buffer,一個(gè)字節(jié)buffer的長度,將這個(gè)buffer通過以太網(wǎng)發(fā)送出去,buffer內(nèi)部的內(nèi)容全部需要我們手工構(gòu)建。DP83848Send()函數(shù)的設(shè)計(jì)思路來自于分析LWIP官網(wǎng)示例,主要是ethernetif.c中的代碼。下一章我們同樣根據(jù)這份代碼,分析收包邏輯,實(shí)現(xiàn)STM32對以太網(wǎng)上數(shù)據(jù)的監(jiān)聽。


關(guān)鍵字:STM32  STM32F4  DP83848  以太網(wǎng)通信  發(fā)包流程 引用地址:STM32開發(fā)筆記53:STM32F4+DP83848以太網(wǎng)通信指南系列(七)

上一篇:STM32開發(fā)筆記54:STM32F4+DP83848以太網(wǎng)通信指南系列(八)
下一篇:STM32開發(fā)筆記52:STM32F4+DP83848以太網(wǎng)通信指南系列(六)

推薦閱讀

今年4月,馬化騰曾透露微信小程序數(shù)量達(dá)到58萬個(gè),開發(fā)者達(dá)到100萬人,而在今天,騰訊官方發(fā)布的小程序最新的數(shù)據(jù)信息中,微信小程序的數(shù)量已經(jīng)達(dá)到了100萬個(gè),開發(fā)者也增加到了150萬人。短短3個(gè)月的時(shí)間,小程序便實(shí)現(xiàn)了40萬的增加量,開發(fā)者50萬的增加量,這種戰(zhàn)果真是讓人瞠目結(jié)舌。官方表示,微信小程序在場景連接、性能和基礎(chǔ)能力上發(fā)布了百余次新能...
小米手環(huán)4 NFC版現(xiàn)已上線上海公共交通卡(Beta)。  目前,小米手環(huán)4 NFC版已支持上海公共交通卡、深圳通、武漢通、合肥通、長安通、綠城通等城市一卡通,以及京津冀互聯(lián)互通卡、江蘇交通一卡通·蘇州等交通聯(lián)合卡?! ∩显滦∶装l(fā)布了小米手環(huán)4與小米手環(huán)4 NFC版。小米手環(huán)4采用0.95英寸240×120分辨率AMOLED高亮度彩屏,支持77種全彩表盤...
All in Cloud已然勢不可擋。憑借云計(jì)算的彈性擴(kuò)容、按需使用、按量付費(fèi)等優(yōu)勢,云數(shù)據(jù)中心正在蠶食傳統(tǒng)數(shù)據(jù)中心的領(lǐng)地。據(jù) Cisco 全球云指數(shù)測算,“到 2021年,94%的工作負(fù)載和計(jì)算實(shí)例都將在云數(shù)據(jù)中心進(jìn)行處理”。相應(yīng)的,為提升云數(shù)據(jù)中心的效率和性能,正激發(fā)計(jì)算、存儲和網(wǎng)絡(luò)架構(gòu)的演變,如AI加速器、軟件定義網(wǎng)絡(luò) (SDN)、通信網(wǎng)絡(luò)處理器和固...
作者:孫惠柱一百年前,捷克劇作家恰佩克異想天開,在舞臺上造出一大群“萬能機(jī)器人”,人類從此有了robot(機(jī)器人)這個(gè)詞。后來生活模仿戲劇,各種各樣的機(jī)器人真的來到了人的工作和生活中。而戲劇的腳步倒慢了下來——大大落后于后來居上的電影。今天,終于在中國舞臺上看到了機(jī)器人,兩個(gè)清新可愛的機(jī)器人深深打動(dòng)了我,比大多數(shù)舞臺上的“人”都更感...

史海拾趣

問答坊 | AI 解惑

現(xiàn)在還有帶COM口的筆記本嗎?

本信息來自合作QQ群:AVR單片機(jī)學(xué)習(xí)與交流群(17727270) 群管理員在壇子里的ID:銅河 要有COM口,有并口。有網(wǎng)口…

查看全部問答∨

EP3C120F780 等效門數(shù)多少??

EP3C120F780是CYCLONE III 中比較大的FPGA,其相關(guān)介紹資料如下圖: 780個(gè)管腳,F(xiàn)BGA封裝,工業(yè)溫度(-40 到100度),商業(yè)溫度(0~85度) ES: 工程樣品, LEAD-FREE 表示啥意思?   此外上面也沒有介紹,其等效的邏輯門數(shù)量? 這而也 ...…

查看全部問答∨

WINCE USB攝像頭驅(qū)動(dòng)成功,結(jié)果實(shí)時(shí)視頻速度太慢

這是一個(gè)大喜又大悲的結(jié)果,前天搞定了6410下USB攝像頭驅(qū)動(dòng),可以捕獲320X240 YUV420格式圖像,昨天修改成了實(shí)時(shí)視頻流的程序,結(jié)果大失所望,S3C6410的USB HOST是USB1.1協(xié)議的,全速12Mbps,所以我想獲取30FPS的圖像很難呀,實(shí)際測試結(jié)果是160MS一 ...…

查看全部問答∨

獲取-5v電源

用7805獲取+5v電源,當(dāng)然用7905就可以獲取-5v電源 我的想法是,我能不能用運(yùn)放把+5v輸出經(jīng)過運(yùn)放反相輸出做-5電源輸出,我估計(jì)這樣的-5V電源不穩(wěn)定,忘高手說說我的想法行嗎? …

查看全部問答∨

補(bǔ)充一點(diǎn)

關(guān)鍵是ARN9,S3C2410的功耗問題,在有一定的外圍電路時(shí),靜態(tài)功耗和工作功耗?…

查看全部問答∨

(慳錢十月)我的淘寶購物經(jīng)

淘寶購物特點(diǎn)是,一次性的,退不了的,所以\"兵者國之大事,不可不察也\" 一句話,挑最近成交多的,而且貨比三家,再有同賣家談好,別發(fā)生不愉快.   我上淘寶買東西主要有以下幾種方式: 一,急 我對急用的東東,不賣不行非買不可的,我貨比三家后,找 ...…

查看全部問答∨

阻塞賦值和非阻塞賦值,綜合出來硬件上的區(qū)別??

據(jù)我的總結(jié)如下: begin-end語句的各句話是順序執(zhí)行的; fork-join語句各句話是并行執(zhí)行的; 阻塞賦值“=”計(jì)算表達(dá)式和賦值一起進(jìn)行; 非阻塞賦值“<=”先計(jì)算表達(dá)式,再在語句塊中統(tǒng)一賦值; 但是,唉,說實(shí)話還是搞得不明不白的!!比如begin- ...…

查看全部問答∨

STM32F103VC的FSMC同步模式怎么用啊

                                 請教版主主,有沒有相關(guān)的應(yīng)用筆記,我用異步模式可以讀寫,但用同步模式就會跳到硬件錯(cuò)誤中斷。…

查看全部問答∨

BeagleBone 學(xué)習(xí)筆記03_2012_10_08

開貼說說sqlite移植 1)下載sqlite的源碼,解壓后進(jìn)入文件夾,新建build文件夾 2)可使用../configure -help查看配置的參數(shù)說明項(xiàng) 3)進(jìn)入build文件夾使用命令生成makefile文件:../configure --host=arm-arago-linux-gnueabi --prefix=/hom ...…

查看全部問答∨
小廣播
設(shè)計(jì)資源 培訓(xùn) 開發(fā)板 精華推薦

最新單片機(jī)文章

 
EEWorld訂閱號

 
EEWorld服務(wù)號

 
汽車開發(fā)圈

 
機(jī)器人開發(fā)圈

電子工程世界版權(quán)所有 京ICP證060456號 京ICP備10001474號-1 電信業(yè)務(wù)審批[2006]字第258號函 京公網(wǎng)安備 11010802033920號 Copyright ? 2005-2025 EEWORLD.com.cn, Inc. All rights reserved