免费国外b站刺激战场直播app,柴火垛里的疯狂55集,百万日元的女人们,洞房初夜

程序小白
認證:優(yōu)質(zhì)創(chuàng)作者
所在專題目錄 查看專題
單片機應用與驅(qū)動開發(fā)之路:這時的你只需要扣動扳機。
RT-Thread驅(qū)動之路:stm32設備驅(qū)動開發(fā)之uart注冊①
RT-Thread驅(qū)動之路:stm32設備驅(qū)動開發(fā)之uart設備創(chuàng)建②
RT-Thread驅(qū)動之路:stm32設備驅(qū)動開發(fā)之uart操作方法③
RT-Thread驅(qū)動之路:stm32設備驅(qū)動開發(fā)之uart中斷處理④
RT-Thread驅(qū)動之路:stm32設備驅(qū)動開發(fā)之淺析注冊機制⑤
作者動態(tài) 更多
RT-Thread驅(qū)動之路:stm32設備驅(qū)動開發(fā)之HWTIMER開發(fā)①
1星期前
RT-Thread驅(qū)動之路:stm32設備驅(qū)動開發(fā)之SPI總線操作方法③
2星期前
RT-Thread驅(qū)動之路:stm32設備驅(qū)動開發(fā)之SPI對象創(chuàng)建②
2星期前
電子元器件那些事兒:三極管工作區(qū)的判斷如此簡單①
3星期前
RT-Thread驅(qū)動之路:stm32設備驅(qū)動開發(fā)之SPI原理①
11-11 14:37

RT-Thread驅(qū)動之路:stm32設備驅(qū)動開發(fā)之uart中斷處理④


      開篇分割線,我們在上一篇講過了uart相關(guān)的ops函數(shù)集,還有個更重要的就是uart中斷,發(fā)送你可以不用,但是接收什么時候來數(shù)據(jù),數(shù)據(jù)能不能及時的進行處理,這都離不開中斷的作用,所以一般應用中中斷接收是必選項。

      我們在寫uart驅(qū)動的時候,就需要考慮如何將中斷事件(有接收數(shù)據(jù)到達)通知給uart設備驅(qū)動框架(也就是serial層),怎么發(fā)通知呢,當然是調(diào)用uart設備驅(qū)動框架提供的rt_hw_serial_isr函數(shù),設備框架才能知道中斷到底發(fā)生了什么事。函數(shù)原型如下:

      serial:串口設備句柄,來自于哪個串口設備的中斷,對應的句柄就是誰。

      event:中斷事件類型。

      接下來看一下stm32——uart設備中斷處理的真實操作:

/*uart_isr的主要用途:調(diào)用框架層rt_hw_serial_isr,通知上層中斷已經(jīng)發(fā)生*/
static void uart_isr(struct rt_serial_device *serial)
{
    struct stm32_uart *uart;
#ifdef RT_SERIAL_USING_DMA
    rt_size_t recv_total_index, recv_len;
    rt_base_t level;
#endif

    RT_ASSERT(serial != RT_NULL);
    uart = rt_container_of(serial, struct stm32_uart, serial);

    /* UART in mode Receiver -------------------------------------------------*/
    if ((__HAL_UART_GET_FLAG(&(uart->handle), UART_FLAG_RXNE) != RESET) &&
            (__HAL_UART_GET_IT_SOURCE(&(uart->handle), UART_IT_RXNE) != RESET))
    {
        rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND);
    }
   //......這里還有好多處理 例如DMA中斷  發(fā)送中斷等不是重點,不展開了。
}

      這段代碼是uart_isr 的一部分專門處理接收中斷觸發(fā)的數(shù)據(jù),作用很簡單,如果讀數(shù)據(jù)寄存器不為空,且RXNE為中斷使能狀態(tài),則調(diào)用rt_hw_serial_isr觸發(fā)讀數(shù)據(jù)操作,關(guān)于該函數(shù)的響應事件類型如下:

#define RT_SERIAL_EVENT_RX_IND          0x01    /* 接收一個字節(jié)數(shù)據(jù)*/
#define RT_SERIAL_EVENT_TX_DONE         0x02    /* 一個字節(jié)數(shù)據(jù)發(fā)送完成   */
#define RT_SERIAL_EVENT_RX_DMADONE      0x03    /* DMA接收完成 */
#define RT_SERIAL_EVENT_TX_DMADONE      0x04    /* DMA發(fā)送完成*/

      接下來我們看下框架提供的代碼都做了哪些工作?

/* ISR for serial interrupt */
void rt_hw_serial_isr(struct rt_serial_device *serial, int event)
{
    switch (event & 0xff)
    {
        case RT_SERIAL_EVENT_RX_IND:
        {
            int ch = -1;
            rt_base_t level;
            struct rt_serial_rx_fifo* rx_fifo;

            /* interrupt mode receive */
            rx_fifo = (struct rt_serial_rx_fifo*)serial->serial_rx;
            RT_ASSERT(rx_fifo != RT_NULL);

            while (1)
            {
                ch = serial->ops->getc(serial);
                if (ch == -1) break;


                /* disable interrupt */
                level = rt_hw_interrupt_disable();

                rx_fifo->buffer[rx_fifo->put_index] = ch;
                rx_fifo->put_index += 1;
                if (rx_fifo->put_index >= serial->config.bufsz) rx_fifo->put_index = 0;

                /* if the next position is read index, discard this 'read char' */
                if (rx_fifo->put_index == rx_fifo->get_index)
                {
                    rx_fifo->get_index += 1;
                    rx_fifo->is_full = RT_TRUE;
                    if (rx_fifo->get_index >= serial->config.bufsz) rx_fifo->get_index = 0;

                    _serial_check_buffer_size();
                }

                /* enable interrupt */
                rt_hw_interrupt_enable(level);
            }

            /* invoke callback */
            if (serial->parent.rx_indicate != RT_NULL)
            {
                rt_size_t rx_length;

                /* get rx length */
                level = rt_hw_interrupt_disable();
                rx_length = (rx_fifo->put_index >= rx_fifo->get_index)? (rx_fifo->put_index - rx_fifo->get_index):
                    (serial->config.bufsz - (rx_fifo->get_index - rx_fifo->put_index));
                rt_hw_interrupt_enable(level);

                if (rx_length)
                {
                    serial->parent.rx_indicate(&serial->parent, rx_length);
                }
            }
            break;
        }
//.......這部分處理其它的事件響應
}
}

      當觸發(fā)事件為接收一個字符是,那么就開啟讀取一個字符,在進行數(shù)據(jù)存儲時防止數(shù)據(jù)出現(xiàn)異常,關(guān)閉硬件中斷,寫入成功后再次開啟終端,再中斷關(guān)閉時,中斷標記位是有效的,也就是說連續(xù)來的數(shù)據(jù)可能已經(jīng)寫入到了DR寄存器中,所以這個時候就可以連續(xù)讀DR寄存器,直到ch返回-1。這個時候代表這當前已無數(shù)據(jù),判斷當前回調(diào)函數(shù)是否為空,不為空則更新緩沖區(qū)新存入數(shù)據(jù)長度(這個過程依舊是關(guān)中斷執(zhí)行)。得到正確的數(shù)據(jù)長度后,調(diào)用回調(diào)函數(shù)讀取數(shù)據(jù),到這里關(guān)于uart設備驅(qū)動的全部內(nèi)容就結(jié)束了,當然關(guān)于發(fā)送中斷、DMA中斷部分內(nèi)容并沒有深入去講解,感興趣的小伙伴可以自己嘗試分析分析該部分代碼的實現(xiàn)邏輯。

      接下來是我們更感興趣的serial層數(shù)據(jù)的處理,筒子們下期再見~!

聲明:本內(nèi)容為作者獨立觀點,不代表電子星球立場。未經(jīng)允許不得轉(zhuǎn)載。授權(quán)事宜與稿件投訴,請聯(lián)系:editor@netbroad.com
覺得內(nèi)容不錯的朋友,別忘了一鍵三連哦!
贊 2
收藏 3
關(guān)注 138
成為作者 賺取收益
全部留言
0/200
成為第一個和作者交流的人吧