前言
自筆者提出 serialX 串口驅(qū)動(dòng)到今天近半年了,當(dāng)初只在 STM32F4 NUC970 兩個(gè)系列芯片上做過理論驗(yàn)證。一個(gè)是 ARM CM4 核心架構(gòu),一個(gè)是 ARM9。這兩款芯片能完美實(shí)現(xiàn)筆者的需求。
經(jīng)過這半年的實(shí)踐考驗(yàn),筆者還是相信 serialX 的實(shí)力的,最近這幾天筆者嘗試在 N32 AB32 RA6M4 上適配 serialX,下面就向各位匯報(bào)一下適配結(jié)果。
芯片 | STM32F4 | NUC970 | N32 | AB32 | RA6M4 | GD32F4 |
架構(gòu) | CM4 | ARM9 | CM4 | RISC-V | CM33 | CM4 |
N32G45
因?yàn)檫@個(gè)也是 CM4,和 STM32F4 相較而言,可能差別很小。讓筆者感到欣慰的是用`DMA_GetFlagStatus(uart->dma_tx.dma_flag, uart->dma_tx.dma_module) == SET` 代替了 `uart->dmaTxing` 。這是一處小改進(jìn)。
除此之外,沒啥可說的了。
已實(shí)現(xiàn)的功能有:
- 輪詢收發(fā)
- 中斷收發(fā)(可阻塞可非阻塞)
- DMA 收發(fā)(可阻塞可非阻塞)
AB32VG1
從芯片手冊(cè)我們可以看到,它的串口外設(shè)只有“接收一個(gè)字節(jié)完成”和“發(fā)送一個(gè)字節(jié)完成”兩個(gè)中斷。
在 serialX 的設(shè)計(jì)構(gòu)想里,我們希望有個(gè)“發(fā)送寄存器空”中斷。因?yàn)檫@樣很容易啟動(dòng)一次中斷,在中斷里判斷是否有數(shù)據(jù)需要發(fā)送,進(jìn)而啟動(dòng)一次發(fā)送過程。
假如沒有這個(gè)中斷,我們必須通過先寫一個(gè)字節(jié)引起一次“發(fā)送完成中斷”,然后借助這次中斷繼續(xù)判斷是否有數(shù)據(jù)需要發(fā)送。在數(shù)據(jù)所有數(shù)據(jù)發(fā)送完之前,我們還需要有個(gè) flag 標(biāo)識(shí)一下現(xiàn)在處于發(fā)送流程中。
因此,serialX 需要進(jìn)行一些改動(dòng):
`_serial_int_tx` 函數(shù)
// TODO: start tx
#if defined (RT_SERIAL_NO_TXEIT)
if (serial->ops->is_int_txing != RT_NULL && serial->ops->is_int_txing(serial) == RT_FALSE) {
ch = _serial_fifo_pop_data(tx_fifo);
serial->ops->start_tx(serial, ch);
}
#else
serial->ops->start_tx(serial);
#endif
```
`struct rt_uart_ops`
```
#if defined (RT_SERIAL_NO_TXEIT)
rt_bool_t (*is_int_txing)(struct rt_serial_device *serial);
void (*start_tx)(struct rt_serial_device *serial, rt_uint8_t ch);
#else
void (*start_tx)(struct rt_serial_device *serial);
#endif
因?yàn)檫@些改動(dòng),AB32VG1 的底層驅(qū)動(dòng)寫法也就不一樣了,多了一個(gè)判斷是否處于發(fā)送流程中的 api。start_tx stop_tx 也不僅僅是開關(guān)中斷那么簡(jiǎn)單了,需要改變 intTxing 這個(gè) flag 標(biāo)識(shí)發(fā)送流程狀態(tài)。
rt_bool_t ab32_int_txing(struct rt_serial_device *serial)
{
struct ab32_uart *uart;
RT_ASSERT(serial != RT_NULL);
uart = rt_container_of(serial, struct ab32_uart, serial);
return uart->intTxing;
}
static void ab32_start_tx(struct rt_serial_device *serial, rt_uint8_t ch)
{
struct ab32_uart *uart;
RT_ASSERT(serial != RT_NULL);
uart = rt_container_of(serial, struct ab32_uart, serial);
uart->intTxing = RT_TRUE;
hal_uart_control(uart->handle.instance, UART_TXIT_ENABLE, HAL_ENABLE);
hal_uart_write(uart->handle.instance, ch);
}
static void ab32_stop_tx(struct rt_serial_device *serial)
{
struct ab32_uart *uart;
RT_ASSERT(serial != RT_NULL);
uart = rt_container_of(serial, struct ab32_uart, serial);
hal_uart_control(uart->handle.instance, UART_TXIT_ENABLE, HAL_DISABLE);
uart->intTxing = RT_FALSE;
}
為此,我們需要添加個(gè)新配置,components/drivers/Kconfig
config RT_SERIAL_NO_TXEIT
bool "No TX Empty interrupt"
default n
help
Useful only if the chip hasn't Transmit Register Empty interrupt
Such as: AB32 RA6M4
意思是說,當(dāng)芯片沒有“發(fā)送寄存器空中斷”支持的時(shí)候,我們需要用 `intTxing` 代替實(shí)現(xiàn)控制發(fā)送過程。
另外,發(fā)送寄存器也沒有空狀態(tài),`putc` 函數(shù)倒是可以判斷發(fā)送完成標(biāo)志,但是這樣就不能在中斷里調(diào)用 `putc` 了;不加發(fā)送完成判斷,就不能在輪詢發(fā)送中調(diào)用它。總之,輪詢發(fā)送和中斷發(fā)送不用用一樣的 `putc` 函數(shù)了。
已實(shí)現(xiàn)的功能有:
- 中斷收發(fā)(可阻塞可非阻塞)
RA6M4
RA6M4 是一款 CM33 核 ARM 芯片,本以為它比 CM4 高級(jí)可以很容易實(shí)現(xiàn) CM4 上實(shí)現(xiàn)的操作。
但是,筆者也沒有從手冊(cè)中找到“發(fā)送寄存器空中斷”。所以 RA6M4 和 AB32VG1 有一樣的補(bǔ)救處理。
但是,筆者還發(fā)現(xiàn)另外一個(gè)問題,**如果是中斷發(fā)送,每次寫完 TDR 寄存器后,必須重新使能發(fā)送中斷**。不這樣做,就不會(huì)出現(xiàn)發(fā)送完成中斷。
雖然如此,連續(xù)發(fā)送多個(gè)字節(jié)仍然會(huì)出現(xiàn)發(fā)送中斷不觸發(fā)(或丟失)的情況,導(dǎo)致發(fā)送功能完全癱瘓(這也是 `intTxing` 引入的隱患)。
已實(shí)現(xiàn)的功能有:
- 中斷接收(可阻塞可非阻塞)
- 中斷發(fā)送(未完),暫時(shí)可以用輪詢發(fā)送代替
多說兩句,RA6M4 的 SCI 好像可以啟用 FIFO ,這樣一來串口收發(fā)寄存器就是帶 FIFO 的。遺憾的是筆者不會(huì)用啊,有會(huì)用的大佬可以嘗試移植一下,用 FIFO 了就相當(dāng)于用 DMA 了。
GD32F4
這個(gè)也可以做到和 STM32F4 一樣的程度,DMA 沒有發(fā)送標(biāo)志,只能繼續(xù)用 `dmaTxing` 。
已實(shí)現(xiàn)的功能有:
- 輪詢收發(fā)
- 中斷收發(fā)(可阻塞可非阻塞)
- DMA收發(fā)(可阻塞可非阻塞)
注:只分配了 UART0 的 DMA 通道,如果其它的也需要開啟 DMA 請(qǐng)自行修改 `struct gd32_uart uarts` 數(shù)組變量分配 DMA 通道。
注:還有一點(diǎn),rt-studio 里下載的 GD32F4 firmware 庫(kù)版本是很多年前的,現(xiàn)在已經(jīng)改動(dòng)過好幾次了。筆者使用的 `gd32f4xx_usart.h` 版本是 “2020-09-30, V2.1.0, firmware for GD32F4xx” 。如有編譯錯(cuò)誤請(qǐng)升級(jí) firmware 庫(kù)。
結(jié)束語
關(guān)于 serialX 理論的部分,之前的文章已經(jīng)說的夠多了。這次是想在多種平臺(tái)上用實(shí)踐檢驗(yàn)一下 serialX 理論的可行性。經(jīng)過這幾天的投入,最終多多少少有些收獲,還是很欣慰的。
匯總一下,目前可以適配的芯片包括如下幾類
1. 沒有 DMA ,只有串口接收發(fā)送中斷
2. 沒有“發(fā)送寄存器空”狀態(tài)或沒有“發(fā)送寄存器空”中斷
3. 帶接收 IDLE 檢測(cè),帶“發(fā)送寄存器空”中斷
4. 帶 DMA ,并且至少有 DMA 半傳輸中斷和全傳輸中斷
5. 串口外設(shè)自帶收發(fā) FIFO (可認(rèn)為是 DMA ,但是比 DMA 使用更簡(jiǎn)單)
在此,特別感謝[嚜軒公告](https://club.rt-thread.org/u/7c37fff6229d1ccd)支援的開發(fā)板,最終完成了 serialX 在這些平臺(tái)上的實(shí)現(xiàn)。
下期預(yù)告,我們來扒一扒 serialX 的缺陷,對(duì),它的缺陷。準(zhǔn)確的講是在 RTOS 上引入的坑有哪些以及怎么避免。
附 [serialX](https://gitee.com/thewon/serialX) 倉(cāng)庫(kù)地址,感興趣的可以下載最新版 serialX 源碼。本文提到的幾種芯片的驅(qū)動(dòng)也都已提交。
審核編輯:湯梓紅
-
ARM
+關(guān)注
關(guān)注
134文章
9094瀏覽量
367540 -
N32
+關(guān)注
關(guān)注
0文章
18瀏覽量
7210 -
STM32F4
+關(guān)注
關(guān)注
3文章
194瀏覽量
28056 -
RT-Thread
+關(guān)注
關(guān)注
31文章
1289瀏覽量
40124 -
serialX
+關(guān)注
關(guān)注
0文章
7瀏覽量
808
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論