<noframes id="xvf7z">
<address id="xvf7z"></address>

        <output id="xvf7z"></output>
        
        

          <p id="xvf7z"></p>

                <th id="xvf7z"><thead id="xvf7z"><progress id="xvf7z"></progress></thead></th>
                創作

                完善資料讓更多小伙伴認識你,還能領取20積分哦, 立即完善>

                3天內不再提示

                rt-thread 驅動篇(一) serialX 框架理論

                出出 ? 來源:出出 ? 作者:出出 ? 2022-06-21 10:37 ? 次閱讀

                前言

                苦串口驅動久矣!

                現狀

                串口驅動三種工作模式:輪詢、中斷、DMA。

                輪詢模式占用 CPU 最高,但是實現也是最簡單的;DMA 占用 CPU 最少,實現也是最麻煩的;中斷模式居中。

                原串口驅動有以下幾個問題:
                1. 中斷模式,接收有緩存,發送沒緩存
                2. 中斷模式,讀操作是非阻塞的,沒有阻塞讀;寫操作因為沒有緩存,只能阻塞寫,沒有非阻塞寫。
                3. 中斷接收過程,每往發送寄存器填充一個字符,就使用完成量等待發送完成中斷,通過完成量進行進程調度次數和發送數據量同樣多!
                4. DMA 模式比較復雜,在實現上更復雜。
                1. 首先,接收有兩種緩存方案,一種沒有緩存,借用應用層的內存直接做 DMA 接收緩存;一種有緩存,用的和中斷模式下相同的 fifo 數據結構。發送只有一種緩存方式,把應用層內存放到數據隊列里做發送緩存。
                2. 無論哪種緩存方案,都沒有考慮阻塞的問題。而是拋給串口驅動一個內存地址,就返回到應用層了。應用層要么動用 `rt_device_set_rx_indicate` `rt_device_set_tx_complete` 做同步——退化成 poll 模式,失去了 DMA 的優勢;要么繼續干其它工作——拋給串口驅動的內存可能引入隱患。
                3. 為了防止 DMA 工作的時候又有新的讀寫需求,

                對串口驅動的期望

                輪詢模式不在今天討論計劃內。下面所有的討論都只涉及中斷和 DMA 兩種模式。

                • 無論哪種工作模式,都應該有至少一級緩存機制。
                • 無論哪種工作模式,都應該可以設置成阻塞或者非阻塞。
                • 默認是阻塞 io 模式;如果想用非阻塞工作模式,可以通過 open 或者 control 修改。
                • 讀寫阻塞特性是同步的,不存在阻塞寫非阻塞讀或者非阻塞寫阻塞讀兩種模式。
                • 阻塞讀的過程是,沒有數據永久阻塞;有數據無論多少(小于等于期望數據量),返回讀取的數據量。
                • 阻塞寫的過程是,緩存空間為 0 阻塞等待緩存被釋放;緩存空間不足先填滿緩存,繼續等待緩存被釋放;緩存空間足夠,把應用層數據拷貝到驅動緩存。最后返回搬到緩存的數據量。
                • 非阻塞讀的過程是,沒有數據返回 0;有數據,從 fifo 拷貝數據到應用層提供的內存,返回拷貝的數據量。
                • 非阻塞寫的過程是,緩存為 0 ,返回 0;緩存不足返回寫成功了多少數據;緩存足夠,把數據搬移完,返回寫成功的數據量。
                • 無論是輪詢、中斷、DMA 哪種模式,都應該可以實現 STREAM 特性。

                中斷模式下的理論實踐

                注:以下實現是在 NUC970 上完成的,有些特性可能不是通用的。例如,串口外設自帶硬件 fifo ,uart1 是高速 uart 設備,fifo 有 64 字節。uart3 的 fifo 就只有 16 字節。

                定義緩存數據結構

                為實現上述需求,接收和發送都需要有如下一個 fifo

                struct rt_serial_fifo
                {
                   rt_uint32_t buf_sz;
                   /* software fifo buffer */
                   rt_uint8_t *buffer;
                   rt_uint16_t put_index, get_index;
                
                   rt_bool_t is_full;
                };

                > 注:別問我為啥不用 ringbuffer

                大部分還是借用 `struct rt_serial_rx_fifo` 的實現的。增加了個 `buf_sz` 由 fifo 自己維護自己的緩存容量

                針對 fifo 特意定義了三個函數,
                `rt_forceinline rt_size_t _serial_fifo_calc_data_len(struct rt_serial_fifo *fifo)` 計算 fifo 中寫入的數據量
                `rt_forceinline void _serial_fifo_push_data(struct rt_serial_fifo *fifo, rt_uint8_t ch)` 壓入一個數據(不完整實現,具體見下文)
                `rt_forceinline rt_uint8_t _serial_fifo_pop_data(struct rt_serial_fifo *fifo)` 彈出一個數據(不完整實現,具體見下文)

                讀設備過程

                讀設備對應中斷接收。

                rt_inline int _serial_int_rx(struct rt_serial_device *serial, rt_uint8_t *data, int length)
                {
                   rt_size_t len, size;
                   struct rt_serial_fifo* rx_fifo;
                   rt_base_t level;
                   RT_ASSERT(serial != RT_NULL);
                
                   rx_fifo = (struct rt_serial_fifo*) serial->serial_rx;
                   RT_ASSERT(rx_fifo != RT_NULL);
                
                   /* disable interrupt */
                   level = rt_hw_interrupt_disable();
                
                   len = _serial_fifo_calc_data_len(rx_fifo);
                
                   if ((len == 0) &&                // non-blocking io mode
                       (serial->parent.open_flag & RT_DEVICE_OFLAG_NONBLOCKING) == RT_DEVICE_OFLAG_NONBLOCKING) {
                       /* enable interrupt */
                       rt_hw_interrupt_enable(level);
                       return 0;
                   }
                   if ((len == 0) &&                // blocking io mode
                       (serial->parent.open_flag & RT_DEVICE_OFLAG_NONBLOCKING) != RT_DEVICE_OFLAG_NONBLOCKING) {
                       do {
                           /* enable interrupt */
                           rt_hw_interrupt_enable(level);
                
                           rt_completion_wait(&(serial->completion_rx), RT_WAITING_FOREVER);
                
                           /* disable interrupt */
                           level = rt_hw_interrupt_disable();
                
                           len = _serial_fifo_calc_data_len(rx_fifo);
                       } while(len == 0);
                   }
                
                   if (len > length) {
                       len = length;
                   }
                
                   /* read from software FIFO */
                   for (size = 0; size < len; size++)
                   {
                       /* otherwise there's the data: */
                       *data = _serial_fifo_pop_data(rx_fifo);
                       data++;
                   }
                
                   rx_fifo->is_full = RT_FALSE;
                
                   /* enable interrupt */
                   rt_hw_interrupt_enable(level);
                
                   return size;
                }

                簡單說明就是:關中斷,計算緩存數據量,如果為空判斷是否需要阻塞??截愅陻祿?,開中斷。
                這里需要注意的是,拷貝完數據后 fifo 必然不會是 full 的,`rx_fifo->is_full = RT_FALSE` 這句沒有加在 `_serial_fifo_pop_data` 函數,所以上面說它的實現是不完整的。

                寫設備過程

                寫設備對應中斷發送

                rt_inline int _serial_int_tx(struct rt_serial_device *serial, const rt_uint8_t *data, int length)
                {
                   rt_size_t len, length_t, size;
                   struct rt_serial_fifo *tx_fifo;
                   rt_base_t level;
                   rt_uint8_t last_char = 0;
                   RT_ASSERT(serial != RT_NULL);
                
                   tx_fifo = (struct rt_serial_fifo*) serial->serial_tx;
                   RT_ASSERT(tx_fifo != RT_NULL);
                
                   size = 0;
                   do {
                       length_t = length - size;
                       /* disable interrupt */
                       level = rt_hw_interrupt_disable();
                
                       len = tx_fifo->buf_sz - _serial_fifo_calc_data_len(tx_fifo);
                
                       if ((len == 0) &&                // non-blocking io mode
                           (serial->parent.open_flag & RT_DEVICE_OFLAG_NONBLOCKING) == RT_DEVICE_OFLAG_NONBLOCKING) {
                           /* enable interrupt */
                           rt_hw_interrupt_enable(level);
                           break;
                       }
                
                       if ((len == 0) &&                // blocking io mode
                           (serial->parent.open_flag & RT_DEVICE_OFLAG_NONBLOCKING) != RT_DEVICE_OFLAG_NONBLOCKING) {
                           /* enable interrupt */
                           rt_hw_interrupt_enable(level);
                
                           rt_completion_wait(&(serial->completion_tx), RT_WAITING_FOREVER);
                
                           continue;
                       }
                
                       if (len > length_t) {
                           len = length_t;
                       }
                       /* copy to software FIFO */
                       while (len > 0)
                       {
                           /*
                            * to be polite with serial console add a line feed
                            * to the carriage return character
                            */
                           if (*data == '\n' &&
                               (serial->parent.open_flag & RT_DEVICE_FLAG_STREAM) == RT_DEVICE_FLAG_STREAM &&
                               last_char != '\r')
                           {
                               _serial_fifo_push_data(tx_fifo, '\r');
                
                               len--;
                               if (len == 0) break;
                               last_char = 0;
                           } else if (*data == '\r') {
                               last_char = '\r';
                           } else {
                               last_char = 0;
                           }
                
                           _serial_fifo_push_data(tx_fifo, *data);
                
                           data++; len--; size++;
                       }
                
                       /* if the next position is read index, discard this 'read char' */
                       if (tx_fifo->put_index == tx_fifo->get_index)
                       {
                           tx_fifo->is_full = RT_TRUE;
                       }
                
                       // TODO: start tx
                       serial->ops->start_tx(serial);
                
                       /* enable interrupt */
                       rt_hw_interrupt_enable(level);
                   } while(size < length);
                
                   return size;
                }

                簡單說明就是:關中斷,計算 fifo 剩余容量,如果空間不足判斷是否阻塞??截悢祿?,開中斷。
                如果數據沒拷貝完,繼續上述過程,直到所有數據拷貝完成。
                上述函數也實現了 STREAM 打開模式,檢查 “\r”“\n” 不完整的問題。

                特別注意:上述函數并沒有執行寫“發送寄存器”的操作,開中斷前,這里執行了一句 `serial->ops->start_tx(serial)` 用于開啟發送過程(這個的實現可能在不同芯片上略有差異)。

                中斷接收

                       while (1) {
                           ch = serial->ops->getc(serial);
                           if (ch == -1) break;
                           /* if fifo is full, discard one byte first */
                           if (rx_fifo->is_full == RT_TRUE) {
                               rx_fifo->get_index += 1;
                               if (rx_fifo->get_index >= rx_fifo->buf_sz) rx_fifo->get_index = 0;
                           }
                           /* push a new data */
                           _serial_fifo_push_data(rx_fifo, ch);
                
                           /* if put index equal to read index, fifo is full */
                           if (rx_fifo->put_index == rx_fifo->get_index)
                           {
                               rx_fifo->is_full = RT_TRUE;
                           }
                       }
                
                       rt_completion_done(&(serial->completion_rx));

                注:這里的 while 循環是因為 uart 外設自帶硬件 fifo。

                簡單講就是,有接收中斷,就往接收 fifo 中壓入數據,如果 fifo 是滿的,丟棄掉舊數據。

                中斷發送

                       /* calucate fifo data size */
                       len = _serial_fifo_calc_data_len(tx_fifo);
                       if (len == 0) {
                           // TODO: stop tx
                           serial->ops->stop_tx(serial);
                           rt_completion_done(&(serial->completion_tx));
                           break;
                       }
                       if (len > 64) {
                           len = 64;
                       }
                       /* read from software FIFO */
                       while (len > 0) {
                           /* pop one byte data */
                           ch = _serial_fifo_pop_data(tx_fifo);
                
                           serial->ops->putc(serial, ch);
                           len--;
                       }
                       tx_fifo->is_full = RT_FALSE;

                先計算是否還有數據要發送,如果沒有,調用 `serial->ops->stop_tx(serial)` 對應上面的 `serial->ops->start_tx(serial)` 。
                因為硬件自帶 fifo ,這里最多可以連續寫 64 個字節。
                因為發送 fifo 是往外彈出數據的,最后肯定是非滿的。

                未說明的問題

                對于串口設備來講,接收是非預期的,所以串口接收中斷必須一直開著。發送就不一樣了,沒有發送數據的時候是可以不開發送中斷的。
                上文中提到的兩個 ops `start_tx` `stop_tx` 正是開發送中斷使能,關發送中斷使能。另外,它倆還有更重要的作用。

                在 NUC970 的設計上,只要發送寄存器為空就會有發送完成中斷,并不是發送完最后一個字節才產生。正因為這個特性,當開發送中斷使能的時候會立馬進入中斷。在中斷里判斷是否有數據要發送,剛好可以作為“啟動發送”。

                對于其它芯片,如果發送中斷的含義是“發送完最后一個字節”,僅僅使能發送中斷還不夠,還需要軟件觸發發送中斷。這是發送不同于接收的最重要的地方。

                DMA 模式下的實現探討

                為什么上一節叫實踐,這一節變成探討了?
                第一,筆者還沒時間在 NUC970 上完成 DMA 的部分。
                第二,有了上面中斷模式的鋪墊,DMA 模式也是輕車熟路。不覺得 NUC970 的硬件 fifo 就是 DMA 的翻版嗎?

                DMA 模式需要二級緩存機制。第一級緩存和中斷模式用的 fifo 一樣。這樣 read write 兩個函數的實現可以是一樣的。
                在此基礎上,增加一個數組。如下是完整串口設備定義:

                struct rt_serial_device
                {
                   struct rt_device          parent;
                   const struct rt_uart_ops *ops;
                   struct serial_configure   config;
                
                   void *serial_rx;
                   void *serial_tx;
                
                   rt_uint8_t serial_dma_rx[64];
                   rt_uint8_t serial_dma_tx[64];
                
                   cb_serial_tx _cb_tx;
                   cb_serial_rx _cb_rx;
                
                   struct rt_completion completion_tx;
                   struct rt_completion completion_rx;
                };
                typedef struct rt_serial_device rt_serial_t;

                這兩個數組作為 DMA 收發過程的緩存。

                發送數據時,從 serial_tx 的 fifo 拷貝數據到 serial_dma_tx ,啟動 DMA。發送完成后判斷 serial_tx 的 fifo 是否還有數據,有數據繼續拷貝,直到 fifo 為空關閉 DMA 發送。

                接收數據時,在 DMA 中斷里拷貝 `serial_dma_rx` 所有數據到 serial_rx 的 fifo 。如果 DMA 中斷分完成一半中斷和全部傳輸完成兩種中斷??梢苑殖蓛纱沃袛?,每次只處理一半數據,這樣每次往 fifo 倒騰數據的時候,還有一半緩沖區可用,也不至于會擔心倉促。

                我們需要做的工作只有“怎么安全有效啟動 DMA 發送”。

                底層驅動

                以上都是串口設備驅動框架部分,下面說說和芯片操作緊密相關的部分

                init 函數,負責注冊設備到設備樹。
                configure 函數,負責串口外設初始化,包括波特率、數據位、流控等等。還有個重要的工作就是調用引腳復用配置函數。
                control 函數,使能禁用收發等中斷。
                putc 函數,負責寫發送寄存器,寫寄存器前一定先判斷發送寄存器是否可寫是否為空,阻塞等。
                getc 函數,負責讀接收寄存器,讀寄存器前一定先判斷是否有有效數據,如果沒有返回 -1。
                start_tx 函數,使能發送中斷,如果發送寄存器為空,觸發發送中斷。(如果芯片沒有這個特性,需要想辦法觸發發送完成中斷)
                stop_tx 函數,禁用發送中斷。
                中斷回調函數,負責處理中斷,根據中斷狀態調用 `rt_hw_serial_isr` 函數。

                實機驗證

                中斷模式在 NUC970 芯片下經過**千萬級數據**收發測試的考驗。測試環境有如下兩種:

                1. 非阻塞 io;波特率 9600;串口調試工具:USR-TCP232 ,USR 出的調試工具。
                串口調試工具定時 50ms 發送 30 個字符。NUC970 接收到數據后返回接收到的數據。
                2. 阻塞 io;波特率 115200;串口調試工具:USR-TCP232 ,USR 出的調試工具。
                串口調試工具定時 10ms 發送 30 個字符。NUC970 接收到數據后返回接收到的數據。(串口調試助手發送了 200w 字節數據,接收到了相同個數字符?。?/p> image.png

                結論

                因為 NUC970 芯片的特殊性,上面雖說使用的是中斷模式,其實和 DMA 有點兒類似了。假如是沒收發一個字節數據各對應一次中斷,中斷次數會比較多。

                但是,在應用層來看,無論是中斷還是 DMA 都是一樣的——要么阻塞,要么非阻塞。

                審核編輯:湯梓紅

                • 中斷
                  +關注

                  關注

                  5

                  文章

                  586

                  瀏覽量

                  38025
                • dma
                  dma
                  +關注

                  關注

                  2

                  文章

                  310

                  瀏覽量

                  91288
                • 串口驅動
                  +關注

                  關注

                  2

                  文章

                  63

                  瀏覽量

                  16184
                • RT-Thread
                  +關注

                  關注

                  27

                  文章

                  398

                  瀏覽量

                  33671
                • serialX
                  +關注

                  關注

                  0

                  文章

                  5

                  瀏覽量

                  88
                收藏 人收藏

                  評論

                  相關推薦

                  RT-Thread串口使用指南及問題解決方式匯總

                  1、這篇文章主要講解如何適配串口V2驅動,下面以STM32F411RE-NUCLEO的BSP為例,講解如何快速適配到該開發板上 ...
                  發表于 06-23 15:29 ? 1863次 閱讀

                  怎么去解決armv8a移植到rt-smart分支系統中出錯的問題呢

                  系統環境 armv8-a 64位 4核cortex-a35 移植到rt-smart分支系統中 由于rt沒有線程支持aarch64 cortex-a35,因此參考cortex-a72...
                  發表于 06-23 14:57 ? 935次 閱讀

                  NUC980開發板應用 基于NK-980IoT的國學唐詩學習機

                  基于NK-980IoT的國學唐詩學習機 1 項目背景 最近一直在陪小孩學習國學精髓,比如唐詩、宋詞這....
                  的頭像 RTThread物聯網操作系統 發表于 06-23 14:55 ? 301次 閱讀

                  Nuvoton M487開發板環境搭建和程序下載測試入門

                  一、開發板介紹1. 前言很感謝RT-Thread 和 新唐給予的這次評測機會,本次評測的開發板是 新唐的 Nuvoton M487,我們拿到手的...
                  發表于 06-23 14:36 ? 1037次 閱讀

                  基于RT-Thread+RA6M4的智能安防系統詳解

                  ??無論是在家里還是在公司,安防都尤為的重要,與其亡羊補牢,更重要的是防患于未然。安全是目的,防范是....
                  的頭像 物聯網技術分享 發表于 06-23 14:34 ? 51次 閱讀
                  基于RT-Thread+RA6M4的智能安防系統詳解

                  在RT-Thread studio + NK-980IOT環境下使用iperf命令測試四種模式帶寬

                  測試環境開發板:NK-980IOT V1.0 開發環境:RT-Thread studio 2.2.1 + NuWriter v1.18 RT-Thread版本:4.0.5 開...
                  發表于 06-23 14:20 ? 1117次 閱讀

                  怎樣對基于NK-980IOT開發板的SPI NAND Flash進行讀寫測試呢

                  SPI協議其實是包括:Standard SPI、Dual SPI和Queued SPI三種協議接口,分別對應3-wire, 4-wire, 6-wire。 (1)...
                  發表于 06-23 12:05 ? 1210次 閱讀

                  Nuvoton M487開發板的PWM驅動評測步驟分享

                  一、M487 PWM簡介1、EPWM ? 8個獨立PWM 輸出,16位計數器,12位預分頻,最大時鐘 192MHz ? 12位死區時間 ? 計...
                  發表于 06-23 11:56 ? 448次 閱讀

                  簡要分析N9H30開發板RTThread框架下的LVGL demo源碼

                  續接上一篇文章,分析LVGL的demo源碼。官方的widget例程代碼lv_demo_widgets()函數體如下,下面逐步分析。雖然之前也簡單看過...
                  發表于 06-23 11:42 ? 358次 閱讀

                  如何利用STM32H743對FDCAN組件驅動進行調試呢

                  簡單記錄下fdcan調試: 1.打開FDCAN組件,啟用FDCAN1 FDCAN2(我修改過KConfig,默認只能啟用FDCAN1) ...
                  發表于 06-23 11:31 ? 346次 閱讀

                  基于NK880IOT和RT-Thread的TIMER硬件使用說明

                  1、NK880IOT-NK9TIMER簡介開發環境簡介NK-980IOT V1.0 (NUC980DK61Y)RT-Thread Studio + J-Link ...
                  發表于 06-23 11:21 ? 775次 閱讀

                  分享一種基于RT-Thread和N32G457的運動姿態解算設計

                  1、基于RT-Thread和N32G457的運動姿態解算基本框架如上圖所示,設計框架由硬件和軟件兩部分組成,其中硬件主要包括N32G45...
                  發表于 06-23 10:24 ? 1076次 閱讀

                  rt-thread 優化系列(五)lwip 裁剪

                  很久之前就開始整理下面的優化項列表了,但是有很多問題研究不深,一時不敢冒失推出。
                  的頭像 出出 發表于 06-23 10:21 ? 837次 閱讀

                  RT-Thread記錄(八、理解RT-Thread內存管理)

                  記得最初學習 RT-Thread ,對于內存管理我也是簡單看看然后一筆帶過,當時覺得用不上,在我做的....
                  的頭像 矜辰所致 發表于 06-23 10:11 ? 188次 閱讀
                  RT-Thread記錄(八、理解RT-Thread內存管理)

                  rt-thread 驅動篇(八)hwtimer 重載算法優化

                  區別于 rt-thread 內核實現的兩種定時器,這種定時器依賴芯片內置的定時器外設,依靠穩定高速的....
                  的頭像 出出 發表于 06-23 10:10 ? 837次 閱讀
                  rt-thread 驅動篇(八)hwtimer 重載算法優化

                  rt-thread 優化系列(四)信號對 ipc 的影響

                  信號 signal,并不是線程間同步的信號量 semaphore。后者是線程間同步機制的一種,而前者....
                  的頭像 出出 發表于 06-23 09:51 ? 825次 閱讀

                  rt-thread優化系列(三)軟定時器的定時漂移問題分析

                  所謂軟定時器,是由一個線程運行維護的定時器列表。由線程調用定時器回調函數。
                  的頭像 出出 發表于 06-23 09:35 ? 835次 閱讀

                  GD32 RISC-V系列 BSP框架制作與移植

                  ? 手把手教你使用RT-Thread制作GD32 RISC-V系列BSP 熟悉RT-Thread的朋....
                  的頭像 嵌入式大雜燴 發表于 06-22 19:44 ? 1527次 閱讀
                  GD32 RISC-V系列 BSP框架制作與移植

                  RT-Thread記錄(七、IPC機制之郵箱、消息隊列)

                  講完了線程同步的機制,我們要開始線程通訊的學習,
                  的頭像 矜辰所致 發表于 06-22 10:06 ? 179次 閱讀
                  RT-Thread記錄(七、IPC機制之郵箱、消息隊列)

                  rt-thread 驅動篇(三) serialX 壓力測試

                  本周筆者花了好多天的時間,計劃從多個方面對串口驅動做個比較。下面就從以下幾個角度做個對比測試。
                  的頭像 出出 發表于 06-22 09:22 ? 1247次 閱讀

                  rt-thread 驅動篇(二) serialX 理論實現

                  在前一篇文章里,大致提出了我的串口驅動框架理論。里面做了一些對串口驅動特性的幻想。也在 NUC970....
                  的頭像 出出 發表于 06-22 09:03 ? 1345次 閱讀
                  rt-thread 驅動篇(二) serialX 理論實現

                  GD32407V-START開發板的BSP框架制作與移植

                  熟悉RT-Thread的朋友都知道,RT-Thread提供了許多BSP,但不是所有的板子都能找到相應....
                  的頭像 嵌入式大雜燴 發表于 06-22 08:54 ? 1286次 閱讀
                  GD32407V-START開發板的BSP框架制作與移植

                  RT-Thread記錄(六、IPC機制之信號量互斥量事件集)

                  上文說到 RT-Thread 對臨界區的處理方式有多種,其中已經分析了關閉調度器和屏蔽中斷的方式, ....
                  的頭像 矜辰所致 發表于 06-21 10:40 ? 2213次 閱讀
                  RT-Thread記錄(六、IPC機制之信號量互斥量事件集)

                  rt-thread 優化系列(二) 之 同步和消息關中斷分析

                  書接前文,上篇優化聊的是關中斷操作,在很多地方過保護,導致關中斷時間太久,可能引起其它中斷不能及時響....
                  的頭像 出出 發表于 06-21 09:47 ? 1836次 閱讀

                  rt-thread 優化系列(一) 之 過多關中斷

                  關于優化的話題永遠不過時,沒期限。
                  的頭像 出出 發表于 06-21 09:03 ? 1421次 閱讀

                  rt-thread 優化系列(0) SysTick 優化分析

                  論壇里有人提出了一個疑問,說 STM32 系列 bsp 在初始化系統時鐘的過程中使用到了 tick ....
                  的頭像 出出 發表于 06-21 08:55 ? 1249次 閱讀

                  RT-Thread記錄(五、RT-Thread 臨界區保護)

                  本文聊聊臨界區,以及RT-Thread對臨界區的處理
                  的頭像 矜辰所致 發表于 06-20 16:06 ? 2095次 閱讀
                  RT-Thread記錄(五、RT-Thread 臨界區保護)

                  usbhost驅動相關疑問與調試記錄

                  調試 stm32 的usb host 的艱辛歷程。希望有遇到相同問題的人能從中發現點兒什么。
                  的頭像 出出 發表于 06-20 15:24 ? 176次 閱讀

                  RT-Thread記錄(四、RTT時鐘節拍和軟件定時器)

                  RT-Thread第4課,聽聽 RT-Thread 的心跳,再學習一下基于心跳的軟件定時器使用。
                  的頭像 矜辰所致 發表于 06-20 11:50 ? 2066次 閱讀
                  RT-Thread記錄(四、RTT時鐘節拍和軟件定時器)

                  rt-thread 驅動篇(六)serialX弊端及解決方法

                  serialX 作為一個非阻塞串口驅動框架,在遇到一些異常時,需要做一些特殊處理,今天,筆者帶大家來....
                  的頭像 出出 發表于 06-20 11:43 ? 239次 閱讀

                  RT-Thread記錄(三、RT-Thread線程操作函數)

                  講完了RT-Thread開發環境,啟動流程,啟動以后當然是開始跑線程了,那么自然我們得學會如何創建線....
                  的頭像 矜辰所致 發表于 06-20 00:31 ? 1731次 閱讀
                  RT-Thread記錄(三、RT-Thread線程操作函數)

                  RT-Thread記錄(二、RT-Thread內核啟動流程)

                  在前面我們RT-Thread Studio工程基礎之上講一講RT-Thread內核啟動流程.
                  的頭像 矜辰所致 發表于 06-20 00:30 ? 1797次 閱讀
                  RT-Thread記錄(二、RT-Thread內核啟動流程)

                  RT-Thread記錄(一、版本開發環境及配合CubeMX)

                  RT-Thread 學習記錄的第一篇文章,RT-Thread記錄(一、RT-Thread 版本、RT....
                  的頭像 矜辰所致 發表于 06-20 00:28 ? 1801次 閱讀
                  RT-Thread記錄(一、版本開發環境及配合CubeMX)

                  基于Select/Poll實現并發服務器(二)

                  開發環境: RT-Thread版本:4.0.3 操作系統:Windows10 Keil版本:V5.3....
                  的頭像 嵌入式大雜燴 發表于 06-20 00:26 ? 1836次 閱讀
                  基于Select/Poll實現并發服務器(二)

                  基于Select/Poll實現并發服務器(一)

                  ? 開發環境: RT-Thread版本:4.0.3 操作系統:Windows10 Keil版本:V5....
                  的頭像 嵌入式大雜燴 發表于 06-20 00:20 ? 1763次 閱讀
                  基于Select/Poll實現并發服務器(一)

                  MPU6050簡介及rt-thread軟件包使用

                  小伙伴們大家好,好久不更新RT-Thread實戰筆記啦,今天來搞一搞MPU6050,話不多說,淦!
                  的頭像 RTThread物聯網操作系統 發表于 06-17 10:42 ? 233次 閱讀

                  使用memheap內存管理算法對片內RAM和片外SDRAM進行管理的方法

                  ??在開發中由于單片機自帶的 RAM 空間比較小,有時候需要擴展片外的 RAM 以供使用,RT-Th....
                  的頭像 RT-Thread 操作系統 發表于 06-17 08:53 ? 262次 閱讀
                  使用memheap內存管理算法對片內RAM和片外SDRAM進行管理的方法

                  RT-Thread自動初始化機制

                  ??在分析之前首先查閱 RT-Thread 的官方文檔 [RT-Thread 自動初始化機制](ht....
                  的頭像 RT-Thread 操作系統 發表于 06-17 08:52 ? 203次 閱讀
                  RT-Thread自動初始化機制

                  rt-thread 驅動篇(五)serialX 小試牛刀

                  終于來到了 serialX 的實踐篇,期待很久了。
                  的頭像 出出 發表于 06-16 11:29 ? 241次 閱讀
                  rt-thread 驅動篇(五)serialX 小試牛刀

                  AT組件的實現過程和代碼的調用邏輯

                  AT組件的核心處理邏輯是將收到的 AT 模組的應答信息放到 recv_line_buf 緩沖區中,然....
                  的頭像 RT-Thread 操作系統 發表于 06-15 09:21 ? 204次 閱讀
                  AT組件的實現過程和代碼的調用邏輯

                  想要使用AI卻不會AI建模嗎

                  人類經歷了三次工業革命,無論是蒸汽機、電力還是電子信息技術,每一次革命都給人類的生產力帶來了幾十倍的....
                  的頭像 科技綠洲 發表于 06-14 14:29 ? 729次 閱讀

                  nr_micro_shell介紹及使用方法

                  在進行調試和維護時,常常需要與單片機進行交互,獲取、設置某些參數或執行某些操作,nr_micro_s....
                  的頭像 MCU開發加油站 發表于 06-13 16:58 ? 381次 閱讀

                  rt-thread 驅動篇(七)GPIO驅動

                  一提 GPIO 可能會讓很多人覺得不屑,這么簡單的東西有什么可說的,也就是一個拉低拉高,誰不會呢。
                  的頭像 出出 發表于 06-13 09:48 ? 400次 閱讀

                  中斷方式和DMA方式有什么不同

                  1、中斷方式是在數據緩沖寄存區滿后,發中斷請求,CPU進行中斷處理。
                  的頭像 嵌入式應用開發 發表于 06-10 11:44 ? 3388次 閱讀
                  中斷方式和DMA方式有什么不同

                  rt-thread 驅動篇(四)serialX 多架構適配

                  自筆者提出 serialX 串口驅動到今天近半年了,當初只在 STM32F4 NUC970 兩個系列....
                  的頭像 出出 發表于 06-10 10:21 ? 303次 閱讀

                  RT-Thread專業版實現對于龍芯全系列處理器支持

                  近日,在龍芯中科與睿賽德科技的共同努力下,RT-Thread專業版已實現了對LoongArch32和....
                  的頭像 科技綠洲 發表于 06-09 16:45 ? 756次 閱讀

                  龍芯中科LoongArch自主指令系統為產業生態保駕護航

                  目前,龍芯中科業務已全部轉向 LoongArch 自主指令系統架構,龍芯 2K1000LA 處理器的....
                  的頭像 科技綠洲 發表于 06-08 11:10 ? 331次 閱讀

                  RT-Thread 4.1.0正式添加對Arm Compiler 6支持

                  在 RT-Thread 4.1.0 正式發布版中,添加了對 Arm Compiler 6 的支持,用....
                  的頭像 科技綠洲 發表于 06-01 15:20 ? 335次 閱讀
                  RT-Thread 4.1.0正式添加對Arm Compiler 6支持

                  Cortex-M0處理器內核異常中斷簡介

                  在Cortex‐M0內核上搭載了一個異常響應系統,支持眾多的系統異常和外部中斷。其中,編號為1-15....
                  的頭像 安芯教育科技 發表于 06-01 14:41 ? 328次 閱讀

                  RT-Thread 4.1.0 正式發布版中的ArmClang

                  ArmClang 相較于 Armcc, 支持的架構更多,Armcc支持到Armv7架構,armcla....
                  的頭像 RTThread物聯網操作系統 發表于 06-01 09:24 ? 271次 閱讀