<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                企業??AI智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                網卡發送數據是通過low\_level\_output()函數實現的,該函數是一個底層驅動函數,這要求用戶熟悉網卡底層特性,還要熟悉pbuf數據包。首先說說發送數據的過程,用戶在應用層想要通過一個網卡發送數據,那么就要將數據傳入LwIP內核中,經過內核的傳輸層封裝、IP層封裝等等,簡單來說就是上層將要發送的數據層層封裝,存儲在pbuf數據包中,可能數據很大,想要多個pbuf才能存放得下,這時候pbuf就以鏈表的形式存在,當數據發送的時候,就要將屬于一個數據包的數據全部發送出去,此處需要注意的是,屬于同一個數據包中的所有數據都必須放在同一個以太網幀中發送。low\_level\_output()函數的實現具體見 ``` 1 static err_t low_level_output(struct netif *netif, struct pbuf *p) 2 { 3 err_t errval; 4 struct pbuf *q; 5 uint8_t *buffer = (uint8_t *)(heth.TxDesc->Buffer1Addr); 6 __IO ETH_DMADescTypeDef *DmaTxDesc; 7 uint32_t framelength = 0; 8 uint32_t bufferoffset = 0; 9 uint32_t byteslefttocopy = 0; 10 uint32_t payloadoffset = 0; 11 DmaTxDesc = heth.TxDesc; 12 bufferoffset = 0; 13 14 /* copy frame from pbufs to driver buffers */ 15 for (q = p; q != NULL; q = q->next) (1) 16 { 17 /* Is this buffer available? If not, goto error */ 18 if ((DmaTxDesc->Status & ETH_DMATXDESC_OWN) != (uint32_t)RESET) 19 { 20 errval = ERR_USE; 21 goto error; (2) 22 } 23 24 /* Get bytes in current lwIP buffer */ 25 byteslefttocopy = q->len; (3) 26 payloadoffset = 0; 27 28 /* Check if the length of data to copy is bigger than Tx buffer size*/ 29 while ( (byteslefttocopy + bufferoffset) > ETH_TX_BUF_SIZE ) (4) 30 { 31 /* Copy data to Tx buffer*/ 32 memcpy( (uint8_t*)((uint8_t*)buffer + bufferoffset), 33 (uint8_t*)((uint8_t*)q->payload + payloadoffset), 34 (ETH_TX_BUF_SIZE - bufferoffset) ); (5) 35 36 /* Point to next descriptor */ 37 DmaTxDesc = (ETH_DMADescTypeDef *)(DmaTxDesc->Buffer2NextDescAddr); (6) 38 39 /* Check if the buffer is available */ 40 if((DmaTxDesc->Status & ETH_DMATXDESC_OWN) != (uint32_t)RESET) 41 { 42 errval = ERR_USE; 43 goto error; (7) 44 } 45 46 buffer = (uint8_t *)(DmaTxDesc->Buffer1Addr); (8) 47 48 byteslefttocopy = byteslefttocopy - (ETH_TX_BUF_SIZE - bufferoffset); 49 payloadoffset = payloadoffset + (ETH_TX_BUF_SIZE - bufferoffset); 50 framelength = framelength + (ETH_TX_BUF_SIZE - bufferoffset); 51 bufferoffset = 0; (9) 52 } 53 54 /* Copy the remaining bytes */ 55 memcpy( (uint8_t*)((uint8_t*)buffer + bufferoffset), 56 (uint8_t*)((uint8_t*)q->payload + payloadoffset), byteslefttocopy ); 57 bufferoffset = bufferoffset + byteslefttocopy; 58 framelength = framelength + byteslefttocopy; (10) 59 } 60 61 /* Prepare transmit descriptors to give to DMA */ 62 HAL_ETH_TransmitFrame(&heth, framelength); (11) 63 64 errval = ERR_OK; 65 66 error: 67 68 /* When Transmit Underflow flag is set, clear it and issue a 69 Transmit Poll Demand to resume transmission */ 70 if ((heth.Instance->DMASR & ETH_DMASR_TUS) != (uint32_t)RESET) 71 { 72 /* Clear TUS ETHERNET DMA flag */ 73 heth.Instance->DMASR = ETH_DMASR_TUS; (12) 74 75 /* Resume DMA transmission*/ 76 heth.Instance->DMATPDR = 0; (13) 77 } 78 return errval; 79 } ``` (1):前面也說了,可能一個pbuf沒法存儲所有的數據,LwIP就會使用鏈表形式的pbuf將所有屬于一個數據包的數據存儲起來,那么在發送的時候就要變量這個pbuf鏈表,將所有數據都取出來。 (2):判斷一下要發送數據的緩沖區可用嗎?如果不可用,就跳轉錯誤。 (3):獲取pbuf中的數據長度。 (4):檢查要拷貝的數據長度是否大于ETH_TX_BUF_SIZE的大小,當數據長度大于以太網發送緩沖區的時候,就需要分批次拷貝了。 (5):將pbuf中payload指向數據區域的數據拷貝到緩沖區,拷貝的大小就是緩沖區的大小。 (6):指向下一個發送的描述符(描述符是STM32以太網中的一種數據結構,此處了解一下即可)。 (7):檢查一下要發送數據的緩沖區可用嗎?如果不可用,就跳轉錯誤。 (8):得到新的buff地址。 (9):計算還需要拷貝的長度、得到要偏移的數據地址、記錄已經拷貝的長度,重新進行拷貝,直到要拷貝的數據長度小于ETH_TX_BUF_SIZE的大小。 (10):退出了while循環,拷貝剩余的數據,并記錄拷貝了多大的數據。 (11):提供傳輸描述符及長度給DMA啟動發送。 (12):當發送錯誤的時候,清除TUS ETHERNET DMA標志位。 (13):重新恢復DMA傳輸。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看