日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

LWIP:RTThread + LWIP

發布時間:2024/3/26 编程问答 42 豆豆
生活随笔 收集整理的這篇文章主要介紹了 LWIP:RTThread + LWIP 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1. 序言

  • 今天跟大家簡單分享 LWIP + RTThread 的移植注意事項,記得以前剛接觸 LWIP 那會,是跟著野火的教程一起走,而大部分 LWIP 移植教程都是以 freeRTOS 為主,本著支持 RTThread 的想法,在當時就想著移植 LWIP 到 RTThread 上,沒想到翻車了,sockets 連接總是連接不上而 netconn 就可以,后面就放棄了…………,直到現在,把它撿起來!
  • 本文僅簡單描述其中需要注意的事項,需要對 RTThread 和 LWIP 有一定的了解,詳細的移植教程無法做到一一細說,還是建議大家去看看野火的教程《LwIP 應用開發實戰指南》和 《RT-Thread 內核實現與應用開發實戰指南》,都是不錯的入門書籍(本文也引用了一些資料)。
  • 基于STM32 + RTThread Nano 3.1.3 + LWIP 2.1.3,當然直接使用全功能的RT-Thread IoT 就可以直接擁有豐富的網絡協議,但是對于一些僅需要簡單的TCP/UDP應用,也是一個不錯的移植選擇方案。

2. 實現

  • 實現phy的底層驅動文件。
  • 移植RTThread Nano 到工程。
  • 移植LWIP文件到工程,使用STM32CubeMX勾選LWIP協議,參照生成的工程實現ethernetif.c文件。
  • 移植sys_arch.c文件(非常重要)。
  • /** 主要實現的內容:內核郵箱、內核互斥量、內核信號量、內核線程創建、內核保護* 可參照STM32CubeMX生成的sys_arch.c* */ #include <lwip/stats.h> #include <lwip/debug.h> #include <string.h> #include "lwip/def.h" #include "lwip/sys.h" #include <lwip/opt.h> #include <lwip/arch.h> #include "tcpip.h" #include "rtthread.h"/*------------------------IPC郵箱實現-------------------------------------------*/uint32_t mbox_count=0; //用于對象容器名稱計數err_t sys_mbox_new(sys_mbox_t *mbox, int size) {char s1[]="RT_MBX";char s2=mbox_count+'0';char *s3=s1+s2;mbox_count++; *mbox = rt_mb_create(s3,(rt_ubase_t)size,RT_IPC_FLAG_PRIO);if(*mbox == NULL) {return ERR_MEM;}return ERR_OK; }void sys_mbox_free(sys_mbox_t *mbox) {rt_mb_delete(*mbox); }void sys_mbox_post(sys_mbox_t *mbox, void *msg) {rt_base_t ret;//由于RTThread郵箱大小為4個字節,所以這里傳遞的是指針指向的地址while(ERR_OK != rt_mb_send_wait(*mbox, (rt_uint32_t)msg, RT_WAITING_FOREVER)); }err_t sys_mbox_trypost(sys_mbox_t *mbox, void *msg) {rt_base_t ret;//由于RTThread郵箱大小為4個字節,所以這里傳遞的是指針指向的地址ret = rt_mb_send(*mbox, (rt_uint32_t)msg);if (ret == RT_EOK) {return ERR_OK;} else {return ERR_MEM;} }err_t sys_mbox_trypost_fromisr(sys_mbox_t *mbox, void *msg) {return sys_mbox_trypost(mbox, msg); }u32_t sys_arch_mbox_fetch(sys_mbox_t *mbox, void **msg, u32_t timeout_ms) {rt_base_t ret;void *msg_dummy;if (!msg) {msg = &msg_dummy;}if (!timeout_ms) {/* wait infinite */ret = rt_mb_recv(*mbox, (rt_uint32_t*)msg, RT_WAITING_FOREVER);} else {rt_tick_t timeout_ticks = timeout_ms;ret = rt_mb_recv(*mbox, (rt_uint32_t*)msg, timeout_ticks);if (ret != RT_EOK) {/* timed out */*msg = NULL;return SYS_ARCH_TIMEOUT;}}/* Old versions of lwIP required us to return the time waited.This is not the case any more. Just returning != SYS_ARCH_TIMEOUThere is enough. */return 1; }u32_t sys_arch_mbox_tryfetch(sys_mbox_t *mbox, void **msg) {rt_base_t ret;void *msg_dummy;if (!msg) {msg = &msg_dummy;}ret = rt_mb_recv(*mbox, (rt_uint32_t*)&(*msg), 0);if (ret != RT_EOK) {*msg = NULL;return SYS_MBOX_EMPTY;}/* Old versions of lwIP required us to return the time waited.This is not the case any more. Just returning != SYS_ARCH_TIMEOUThere is enough. */return 1; }int sys_mbox_valid(sys_mbox_t *mbox) {if (*mbox == NULL)return 0;elsereturn 1; }void sys_mbox_set_invalid(sys_mbox_t *mbox) {*mbox = NULL; }/*----------------------------IPC信號量實現---------------------------------*/uint32_t sem_count=0; //用于對象容器名稱計數err_t sys_sem_new(sys_sem_t *sem, u8_t initial_count) {char s1[]="RT_SEM";char s2=sem_count+'0';char *s3=s1+s2;sem_count++;*sem = rt_sem_create(s3,1,RT_IPC_FLAG_PRIO);if(*sem == NULL) {return ERR_MEM;}if(initial_count == 0) {rt_sem_trytake(*sem);}else if(initial_count == 1) {rt_base_t ret = rt_sem_release(*sem);}return ERR_OK; }u32_t sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout_ms) {rt_base_t ret;if(!timeout_ms) {/* wait infinite */ret = rt_sem_take(*sem, RT_WAITING_FOREVER);} else {rt_tick_t timeout_ticks = timeout_ms;ret = rt_sem_take(*sem, timeout_ticks);if (ret != RT_EOK) {/* timed out */return SYS_ARCH_TIMEOUT;}}/* Old versions of lwIP required us to return the time waited.This is not the case any more. Just returning != SYS_ARCH_TIMEOUThere is enough. */return 1; }void sys_sem_signal(sys_sem_t *sem) {rt_base_t ret;ret = rt_sem_release(*sem); }void sys_sem_free(sys_sem_t *sem) {rt_sem_delete(*sem); }int sys_sem_valid(sys_sem_t *sem) {if (*sem == NULL)return 0;elsereturn 1; }void sys_sem_set_invalid(sys_sem_t *sem) {*sem = NULL; }/*----------------------------IPC互斥量---------------------------------*/#if LWIP_COMPAT_MUTEX == 0uint32_t mutex_count=0; //用于對象容器名稱計數err_t sys_mutex_new(sys_mutex_t *mutex) {char s1[]="RT_MUTEX";char s2=mutex_count+'0';char *s3=s1+s2;mutex_count++;*mutex = rt_mutex_create(s3,RT_IPC_FLAG_PRIO);if(*mutex == NULL) {return ERR_MEM;}return ERR_OK; }void sys_mutex_free(sys_mutex_t *mutex) {rt_mutex_delete(*mutex); }void sys_mutex_lock(sys_mutex_t *mutex) {rt_base_t ret;ret = rt_mutex_take(*mutex, RT_WAITING_FOREVER); }void sys_mutex_unlock(sys_mutex_t *mutex) {rt_base_t ret;ret = rt_mutex_release(*mutex); }#endif/*----------------------------IPC線程---------------------------------*/sys_thread_t sys_thread_new(const char *name, lwip_thread_fn thread, void *arg, int stacksize, int prio) {rt_base_t ret;sys_thread_t lwip_thread;size_t rtos_stacksize;rtos_stacksize = (size_t)stacksize;lwip_thread = rt_thread_create(name,thread,arg,rtos_stacksize,prio,50); rt_thread_startup(lwip_thread);return lwip_thread; }/*----------------------------保護內存申請等---------------------------------*///強烈建議在lwipopts.h將該宏打開, //SYS_LIGHTWEIGHT_PROT宏實現可以用于保護內核申請內存時通過互斥量保護, //可以有效避免由于內存申請出現的錯誤。#if SYS_LIGHTWEIGHT_PROT == 1sys_mutex_t lwip_sys_mutex; //內存保護void sys_init(void) {lwip_sys_mutex = rt_mutex_create("RT_MUTEX_PRO",RT_IPC_FLAG_PRIO); }sys_prot_t sys_arch_protect(void) {rt_base_t ret;ret = rt_mutex_take(lwip_sys_mutex, RT_WAITING_FOREVER);return 1; }void sys_arch_unprotect(sys_prot_t pval) {LWIP_UNUSED_ARG(pval);rt_base_t ret;ret = rt_mutex_release(lwip_sys_mutex);} //void sys_arch_msleep(u32_t delay_ms) //{ // rt_thread_delay(delay_ms); //}#endif/*-----------------------------LWIP時間計數-------------------------------------*/u32_t sys_now(void) {return rt_tick_get(); }u32_t sys_jiffies(void) {return rt_tick_get(); }
  • 由于RTThread線程啟動的特殊性,main函數是在一個線程里面被調用執行的,如果在main函數里面創建更高優先級的線程,就會馬上執行高優先級線程,且一般我們會把網口的處理接收ethernetif_input單獨作為一個線程來運行,通過ETH外設中斷發送信號量使接收線程ethernetif_input運行,因此,我們需要在初始化LWIP內核和網口的初始化時,禁止中斷和線程調度,避免LWIP內核未完成初始化時,ethernetif_input線程運行或發生中斷過程中使用了內核信號量,但內核并沒初始化出信號量,就會發生錯誤。
  • //偽代碼 rt_base_t ret =rt_hw_interrupt_disable(); ..... LAN8720_Init(); tcpip_init(NULL,NULL); .... rt_hw_interrupt_enable(ret);
  • 一般使用的線程優先級,讓LWIP內核線程反應更快。
  • 宏:SYS_LIGHTWEIGHT_PROT,開啟后并用互斥量實現,能夠保護內核在申請內存時安全。(sys_init初始化互斥量、sys_arch_protect申請互斥量、sys_arch_unprotect釋放互斥量)
  • 宏:LWIP_TCPIP_CORE_LOCKING,不開啟時用戶線程發送郵箱信息到tcpip線程,tcpip線程再來處理回調,如下圖,這增加了系統開銷(線程切換,從用戶線程切換到tcpip線程),若開啟后用戶線程會申請互斥量,保護用戶線程的運行,直接調用回調函數。建議開啟。

  • 總結

    以上是生活随笔為你收集整理的LWIP:RTThread + LWIP的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 刘玥91精选国产在线观看 | 日本高清免费观看 | 日韩一区二区三区在线观看视频 | 伊人精品在线观看 | 国内自拍欧美 | 天天爱天天爽 | 性欧美jzjz2 九草影院 | av中文字幕网站 | 99精品视频在线观看 | a天堂在线观看 | 国产乱子伦精品 | 日本一本在线 | 想要xx在线观看 | 国产成a人亚洲精v品无码 | 一级黄色小视频 | 色噜噜狠狠一区二区三区牛牛影视 | 91久久伊人 | 啪啪无遮挡 | 精品日韩在线播放 | 欧美91精品久久久久国产性生爱 | 日本一区二区免费高清视频 | www.jizzjizz.com| 国产福利91精品一区二区三区 | 日本美女黄视频 | 国产女教师一区二区三区 | 韩国一二三区 | 91喷水视频 | 欧性猛交ⅹxxx乱大交 | h片在线免费看 | 亚洲天堂久久久 | 久久精品亚洲a | 夜夜操夜夜 | 欧洲精品一区 | h片网站在线观看 | 美女的胸给男人玩视频 | 99热国 | 美女操出白浆 | 怡红院亚洲 | 黄色污网站在线观看 | 中文一二区 | 亚洲欧美国产视频 | 手机av在线 | 亚洲情se | 亚洲自拍激情 | 中文一区二区 | 无码精品国产一区二区三区 | 亚洲精品乱码久久久久久按摩观 | 黄频在线免费观看 | 93久久精品日日躁夜夜躁欧美 | 亚洲日本成人在线观看 | 免费国产一级 | 日本视频在线免费观看 | 成人高潮片免费网站 | 日韩毛片在线播放 | 国产精品日韩欧美大师 | 国产乱码一区二区三区在线观看 | jizz成人| 在线观看麻豆 | 97视频在线观看免费 | 色屁屁一区二区三区 | 日韩在线不卡 | 综合婷婷| 人人舔人人插 | 91av影视 | 一区二区三区精彩视频 | 可以免费看污视频的网站 | 亚洲av无码国产精品久久久久 | 欧美三级视频在线播放 | 亚州av综合色区无码一区 | 轻轻色在线观看 | 久久精品无码专区免费 | 91sao | 天堂一区二区三区 | 影音先锋中文字幕在线视频 | 国产人妖av| 91精品欧美| 国产美女自拍视频 | 美女福利片 | www.尤物| 成人午夜淫片100集 伊人久久国产 | 我们的生活第五季在线观看免费 | 亚洲高清在线观看 | 欧美日一区二区 | 黄色污污网站在线观看 | 中文字幕色站 | 三级视频网 | 亚洲av日韩av不卡在线观看 | 中国女人特级毛片 | 国产成人精品一区二 | 日韩激情精品 | 日韩精品一区二区三区免费视频 | 日本三级免费网站 | 粉嫩av渣男av蜜乳av | 蜜桃视频久久一区免费观看入口 | 91女神在线| 青青草综合视频 | 男阳茎进女阳道视频大全 | 久久亚洲AV成人无码一二三 | 欧美日韩国产一区二区在线观看 |