|
大家好,我是痞子衡,是正經(jīng)搞技術(shù)的痞子。今天痞子衡給大家介紹的是SDK2.0里事務型中斷處理函數(shù)(DriverIRQHandler)的重定向注意事項。
最近有一個 i.MXRT 客戶在使用官方 SDK 外設(shè)驅(qū)動里的中斷處理函數(shù)時遇到了代碼重定向失效問題,客戶用得是一個 XIP Flash 工程,想把程序中斷向量表以及相關(guān)外設(shè)的驅(qū)動函數(shù)全部重定向到 RAM 中以提高系統(tǒng)性能,但實測發(fā)現(xiàn)中斷發(fā)生時,仍然存在 Flash 訪問行為。這本來不是個大問題,因為 SDK 在設(shè)計時已經(jīng)從中斷處理函數(shù)命名上就做了明確提醒,但是很多客戶并沒有意識到,今天痞子衡就來聊聊這個話題:
一、事務型驅(qū)動函數(shù)簡介恩智浦 SDK 軟件包里的外設(shè)驅(qū)動(HAL級)正常來說提供的 API 都是面對外設(shè)配置(init、deinit、set_feature、get_status) 的通用功能函數(shù)。此外對于通信接口類外設(shè),一般還會有阻塞式(blocking)的數(shù)據(jù)傳輸功能函數(shù)。以 LPUART 外設(shè)為例,其數(shù)據(jù)傳輸有以下四個 API:
// 寫入(發(fā)送)一個 Byte 數(shù)據(jù)(需在 FIFO 沒滿的情況下)
static inline void LPUART_WriteByte(LPUART_Type *base, uint8_t data);
// 讀取(接收)一個 Byte 數(shù)據(jù)(需在 FIFO 非空的情況下)
static inline uint8_t LPUART_ReadByte(LPUART_Type *base);
// 阻塞式寫入(發(fā)送)多個 Byte 數(shù)據(jù)
status_t LPUART_WriteBlocking(LPUART_Type *base, const uint8_t *data, size_t length);
// 阻塞式讀取(接收)多個 Byte 數(shù)據(jù)
status_t LPUART_ReadBlocking(LPUART_Type *base, uint8_t *data, size_t length);
阻塞式數(shù)據(jù)傳輸 API 本質(zhì)上就是獨占 CPU 時間進行查詢式傳輸,API 一旦調(diào)用,必須等到數(shù)據(jù)收發(fā)結(jié)束才會返回,這樣會導致 CPU 利用率不高,其一般不利用外設(shè)中斷。為了結(jié)合外設(shè)中斷進行高效數(shù)據(jù)傳輸(non-blocking),SDK2.0 中額外提供了如下事務型相關(guān)函數(shù)(僅列出了部分):
// 創(chuàng)建事務型數(shù)據(jù)傳輸句柄
void LPUART_TransferCreateHandle(LPUART_Type *base,
lpuart_handle_t *handle,
lpuart_transfer_callback_t callback,
void *userData);
// 非阻塞式寫入(發(fā)送)多個 Byte 數(shù)據(jù)
status_t LPUART_TransferSendNonBlocking(LPUART_Type *base, lpuart_handle_t *handle, lpuart_transfer_t *xfer)
// 非阻塞式讀取(接收)多個 Byte 數(shù)據(jù)
status_t LPUART_TransferReceiveNonBlocking(LPUART_Type *base,
lpuart_handle_t *handle,
lpuart_transfer_t *xfer,
size_t *receivedBytes);
// 事務型數(shù)據(jù)傳輸中斷處理函數(shù)
void LPUART_TransferHandleIRQ(LPUART_Type *base, void *irqHandle);
非阻塞式數(shù)據(jù)傳輸 API 顯然就是結(jié)合了外設(shè)中斷來做數(shù)據(jù)傳輸,API 調(diào)用后填入一些配置后會立刻返回,沒有過多消耗 CPU 時間,等外設(shè)中斷發(fā)生時再進一步處理數(shù)據(jù)。這類型 API 常常和應用設(shè)計緊相關(guān),所以也稱為事務型函數(shù)(transactional API)。
SDK 里并不是所有外設(shè)驅(qū)動里包含事務性函數(shù),這類 API 常出現(xiàn)在傳輸接口類外設(shè)上。對于 i.MXRT 來說,支持此類 API 的外設(shè)有:DMA、LPUART、LPSPI、LPI2C、SAI、FLEXIO、FLEXSPI、USDHC、ENET、CAN、MIPI_DSI/CSI、SPDIF、ASRC、PDM 等。
二、事務型中斷處理函數(shù)設(shè)計這里繼續(xù)以 LPUART 外設(shè)來具體介紹。如下 i.MXRT1011 SDK 里提供的 8 個 LPUART 例程中有 5 個是基于事務型驅(qū)動函數(shù)的,我們就以 interrupt_transfer 的 IAR 工程為例。 |
|