一、UART簡介
i.MX6U 芯片具有多達 8 個 UART 外設用于串口通訊,UART 是在 USART 基礎上裁剪掉了同步通信功能,只支持異步通信。簡單區分同步和異步就是看通信時需不需要對外提供時鐘輸出,我們平時用的串口通信基本都是 UART。
UART 滿足外部設備對工業標準 NRZ 異步串行數據格式的要求,并且使用了小數波特率發生器,可以提供多種波特率,使得它的應用更加廣泛。UART 支持異步單向通信和半雙工單線通信;還支持局域互連網絡 LIN、智能卡(SmartCard)協議與 lrDA(紅外線數據協會)SIR ENDEC 規范。
i.MX6U 的 UART 主要特性如下:
兼容高速 TIA/EIA-232-F,最高 5.0 Mbit/s。
兼容 IrDA 串行低速紅外接口,最高 115.2 Kbit/s。
支持 9 位或多點(Multidrop mode)模式(RS-485)(自動從地址檢測)。
支持 7 位或 8 位 RS-232 格式或 9 位的 RS-485 格式。
支持 1 或 2 位停止位。
可編程奇校驗或偶校驗。
支持硬件流控(CTS/RTS)。
RTS支持邊緣中斷檢測。
自動波特率檢測(最高為115.2kbit/s)。
rx_data 輸入和 tx_data 輸出可分別在 rs-232/rs-485 模式下進行交換(軟件可交換 TX、RX 引腳)。
兩個 DMA 請求(TxFIFODMA 請求和 RxFIFODMA 請求)。
支持軟件復位 (Srst_B)。
兩個獨立的 32 輸入 FIFO,用于發送和接收。
二、引腳分布
相比 STM32,i.MX6U 的串口增加了引腳交換功能。通過配置 UFCR[DCEDTE] 寄存器可以交換 TX、RX 引腳以及 CTS、RTS 引腳,如下圖所示。
三、波特率設置
3.1 串口時鐘
串口模塊共有兩個時鐘輸入 Peripheral Clock 和 Module Clock。
Peripheral Clock
外部時鐘。這個時鐘主要用于讀、寫接收和發送的數據,例如讀接收FIFO、寫發送FIFO。 這個時鐘與波特率設置無關,如果沒有特殊需求我們將這個時鐘保持默認即可,在初始代碼中并沒有特意設置這個時鐘。Module Clock
模塊時鐘,它既可用于接收、發送數據也用于設置波特率,這個時鐘決定了串口最高支持的波特率。Module Clock 時鐘來自根時鐘 UART_CLK_ROOT。
從圖中可以看出,從PLL時鐘到UART時鐘共用用到了兩個時鐘選擇寄存器(標號①和③),兩個時鐘分頻寄存器(標號②和標號④)。 我們最終目的是將PLL3時鐘作為UART根時鐘(UART_CLK_ROOT)的根時鐘。按照標號順序講解如下:
標號①選擇 PLL3 時鐘還是 CCM_PLL3_BYP。我們選擇 PLL3 輸出時鐘,寄存器 CCSR[PLL3_SW_CLK_SEL] = 0, 則表示選擇 PLL3 時鐘。默認情況下是這樣設置的。所以我們代碼中并沒有設置該寄存器。
標號②設置時鐘分頻,根據之前的設置,PLL3 的輸出頻率為 480MHz ,這里的時鐘分頻是固定的 6 分頻, 經過分頻后的時鐘為 480MHz / 6 = 80MHz。
標號③ 再次選擇時鐘源。一個是 PLL3 分頻得到的 80MHz 時鐘,另外一個是 OSC 時鐘即 24MHz 的系統參考時鐘。 設置 CSCDR1[UART_CLK_SEL] = 0,選擇第一個(80MHz)時鐘。
標號④再次進行時鐘分頻。這是一個 6 位的時鐘分頻寄存器。分頻值為 CSCDR1[UART_CLK_PODF] 寄存器值加一。 程序中將其設置為 1,則分頻系數為 2,UART_CLK_ROOT 時鐘頻率實際為 80MHz / 2 = 40MHz。
3.2 波特率計算公式
UART的發送器和接收器使用相同的波特率。計算公式如下:
BaudRate:要設置的波特率。
Ref Freq:參考時鐘,這個時鐘是 Module Clock 經過 RFDIV 寄存器分頻后得到的頻率。
UBMR:UBMR寄存器值。
UBIR:UBIR 寄存器值。
3.3 配置UARTx_UFCR寄存器
假設目標波特率為 115200。
3.3.1 設置時鐘分頻寄存器RFDIV
通過設置時鐘分頻寄存器 RFDIV,得到參考時鐘 Ref Freq。
Ref Freq 時鐘應該被設置為多少,沒有一個準確的數字,遵守以下幾條:
Ref Freq 時鐘要大于波特率的 16 倍。
依據是 module_clock 必須大于等于 16 倍波特率【參考《IMX6ULRM》(參考手冊)53.4.2.1 Clock requirements,而 module_clock 經過 Clock Gating & Divider 之后變為 ref_clk,從功能框圖看 ref_clk 最終作為 uart 模塊參考時鐘】。
UBMR 和 UBIR 的值必須小于 0xFFFF。
module_clock 時鐘經過 UARTx_UFCR[RFDIV] 寄存器分頻后得到 Ref Freq 時鐘,如下圖所示。
在程序中 Module Clock 被設置為 40MHz 而波特率只有 115200,所以這里將分頻值設置為最大值 7,即UARTx_UFCR[RFDIV] = 110B。得到參考時鐘 Ref Freq = 40MHz / 7 = 5.71MHz。
3.3.2 計算UBMR和UBIR的值
已知波特率 115200,參考時鐘 Ref Freq = 5.71MHz,可以計算得到 (UBMR+1) / (UBIR+1) 約為 3.10。 我們設置 (UBIR+1) = 10,(UBMR+1) = 31。
四、接收和發送FIFO
Tx Block 與 Rx Block 包括三部分:
控制單元Control
控制整個串口的工作, 我們編寫軟件不必過多關心。電源管理單元 Power Saving
TxFIFO (和RxFIFO)
TxFIFO 與 RxFIFO 大小均為 32 字節,以發送為例,數據通過 UTXD 寄存器自動寫入 TxFIFO,如果 TxFIFO沒有滿,則可以不斷將數據寫入 UTXD 寄存器。UTS[4] 寄存器是 TxFIFO 滿的標志位。如果關閉了發送,仍然可以向 TxFIFO 寫入數據,但這樣做將會產生傳輸錯誤信息。當 TxFIFO 中的數據發送完成后將會自動設置發送緩沖區空中斷標志位,向 TxFIFO 寫入數據將自動清除發送緩沖區空標志位。
五、DMA和中斷請求
每個串口有兩個 DMA 請求,txfifo dma 請求和 rxfifo dma 請求,有多個中斷請求。
這里只介紹幾個常用的中斷:
中斷事件 | 使能位 | 標志位 |
---|---|---|
空閑中斷 | UARTx_UCR1[TRDYEN] | UARTx_USR2[TXFE] |
接收溢出中斷 | UARTx_UCR4[OREN] | UARTx_USR2[ORE] |
接收緩沖區非空中斷 | UARTx_UCR4[DREN] | UARTx_USR2[RDR] |
完整內容請參考《IMX6ULRM》(參考手冊)53.4.1 Interrupts and DMA Requests。
六、編程流程
1. 創建工程文件夾
2. 移植官方SDK寄存器定義文件
3. 移植野火PAD屬性配置文件
4. 編寫啟動文件
5. 編寫鏈接文件
6. 編寫makefile文件
7. 編寫C語言代碼
(1) 設置UART時鐘源
(2) 初始化UART
(3) 使能UART
(4) UART數據接收
(5) UART數據發送
七、創建工程文件夾
創建一個文件夾 uart
創建一個用于存放頭文件的文件夾 include
創建一個用于存放驅動源碼的文件 device
創建一個啟動文件 start.S
創建一個源文件 main.c
創建一個鏈接腳本 base.lds
八、移植官方SDK寄存器定義文件
在 /uart/include 目錄下添加官方SDK寄存器定義文件 MCIMX6Y2.h,位于 SDK_2.2_MCIM6ULL_EBF6ULL/devices/MCIMX6Y2 目錄下。
在官方SDK的頭文件 MCIMX6Y2.h 文件多達4萬多行,包含了i.MX6U芯片幾乎所有的寄存器定義以及中斷編號的定義。
這里只列 GPIO1相關寄存器 的部分代碼。其他寄存器定義與此類似。 添加這些定義之后我們就可以 直接使用 “GPIO1->DR” 語句操作GPIO1的DR寄存器。操作方法與STM32非常相似。
typedef struct {
__IO uint32_t DR; /**< GPIO data register, offset: 0x0 */
__IO uint32_t GDIR; /**< GPIO direction register, offset: 0x4 */
__I uint32_t PSR; /**< GPIO pad status register, offset: 0x8 */
__IO uint32_t ICR1; /**< GPIO interrupt configuration register1,*/
__IO uint32_t ICR2; /**< GPIO interrupt configuration register2, */
__IO uint32_t IMR; /**< GPIO interrupt mask register, offset: 0x14 */
__IO uint32_t ISR; /**< GPIO interrupt status register, offset: 0x18 */
__IO uint32_t EDGE_SEL;/**< GPIO edge select register, offset: 0x1C */
} GPIO_Type;
/*********************以下代碼省略***************************8*/
/** Peripheral GPIO1 base address */
#define GPIO1_BASE (0x209C000u)
/** Peripheral GPIO1 base pointer */
#define GPIO1 ((GPIO_Type *)GPIO1_BASE)
九、移植野火PAD屬性配置文件
在 /uart/device 目錄下添加 pad_config.h。
通常情況下一個引腳要設置8種PAD屬性,而這些屬性只能通過數字指定。為簡化PAD屬性設置野火編寫了一個PAD屬性配置文件 pad_config.h (embed_linux_driver_tutorial_imx6_code/bare_metal/led_rgb_c/pad_config.h)【源碼下載:https://gitee.com/Embedfire/embed_linux_driver_tutorial_imx6_code.git】,這里使用宏定義了引腳可選的PAD屬性值,并且通過宏定義的名字很容易知道宏代表的屬性值:
/* SPEED 帶寬配置 */
#define SPEED_0_LOW_50MHz IOMUXC_SW_PAD_CTL_PAD_SPEED(0)
#define SPEED_1_MEDIUM_100MHz IOMUXC_SW_PAD_CTL_PAD_SPEED(1)
#define SPEED_2_MEDIUM_100MHz IOMUXC_SW_PAD_CTL_PAD_SPEED(2)
#define SPEED_3_MAX_200MHz IOMUXC_SW_PAD_CTL_PAD_SPEED(3)
/* PUE 選擇使用保持器還是上下拉 */
#define PUE_0_KEEPER_SELECTED IOMUXC_SW_PAD_CTL_PAD_PUE(0)
#define PUE_1_PULL_SELECTED IOMUXC_SW_PAD_CTL_PAD_PUE(1)
/* PUS 上下拉配置 */
#define PUS_0_100K_OHM_PULL_DOWN IOMUXC_SW_PAD_CTL_PAD_PUS(0)
#define PUS_1_47K_OHM_PULL_UP IOMUXC_SW_PAD_CTL_PAD_PUS(1)
#define PUS_2_100K_OHM_PULL_UP IOMUXC_SW_PAD_CTL_PAD_PUS(2)
#define PUS_3_22K_OHM_PULL_UP IOMUXC_SW_PAD_CTL_PAD_PUS(3)
完整的代碼請閱讀源文件,這里只列出了文件“pad_config.h”部分代碼(embed_linux_driver_tutorial_imx6_code/bare_metal/led_rgb_c/pad_config.h)【源碼下載:https://gitee.com/Embedfire/embed_linux_driver_tutorial_imx6_code.git】。
十、編寫啟動文件
在 /uart 下創建 start.S 文件用于編寫啟動文件。
在匯編文件中設置“棧地址”并執行跳轉命令跳轉到main函數執行C代碼。
10.1 完整代碼
/***********************第一部分*********************/
.text //代碼段
.align 2 //設置2字節對齊
.global _start //定義一個全局標號
/*************************第二部分*************************/
_start: //程序的開始
b reset //跳轉到reset標號處
/*************************第三部分*************************/
reset:
mrc p15, 0, r0, c1, c0, 0 /* 將 CP15 協處理器中的寄存器數據讀到 ARM 寄存器中 */
bic r0, r0, #(0x1 << 12) /* 清除第12位(I位)禁用 I Cache */
bic r0, r0, #(0x1 << 2) /* 清除第 2位(C位)禁用 D Cache */
bic r0, r0, #0x2 /* 清除第 1位(A位)禁止嚴格對齊 */
bic r0, r0, #(0x1 << 11) /* 清除第11位(Z位)分支預測 */
bic r0, r0, #0x1 /* 清除第 0位(M位)禁用 MMU */
mcr p15, 0, r0, c1, c0, 0 /* 將 ARM 寄存器的數據寫入到 CP15 協處理器寄存器中 */
/***********************第四部分*********************/
ldr sp, =0x84000000 //設置棧地址64M
b main //跳轉到main函數
/***********************第五部分*******************/
/*進入死循環*/
loop:
b loop
10.2 分析代碼
第一部分
.text 定義代碼段。
.align 2 設置字節對齊。
.global _start 生命全局標號_start。
/*************************第一部分*************************/
.text //代碼段
.align 2 //設置2字節對齊
.global _start //定義一個全局標號
第二部分
_start: 定義標號_start: ,它位于匯編的最前面,說以會首先被執行。
b reset 使用b指令將程序跳轉到reset標號處。
/*************************第二部分*************************/
_start: //程序的開始
b reset //跳轉到reset標號處
第三部分
通過修改CP15寄存器(系統控制寄存器) 關閉 I Cache 、D Cache、MMU 等等。
我們暫時用不到的功能,如果開啟可能會影響我們裸機運行,為避免不必要的麻煩暫時關閉這些功能。
/*************************第三部分*************************/
reset:
mrc p15, 0, r0, c1, c0, 0 /* 將 CP15 協處理器中的寄存器數據讀到 ARM 寄存器中 */
bic r0, r0, #(0x1 << 12) /* 清除第12位(I位)禁用 I Cache */
bic r0, r0, #(0x1 << 2) /* 清除第 2位(C位)禁用 D Cache */
bic r0, r0, #0x2 /* 清除第 1位(A位)禁止嚴格對齊 */
bic r0, r0, #(0x1 << 11) /* 清除第11位(Z位)分支預測 */
bic r0, r0, #0x1 /* 清除第 0位(M位)禁用 MMU */
mcr p15, 0, r0, c1, c0, 0 /* 將 ARM 寄存器的數據寫入到 CP15 協處理器寄存器中 */
第四部分
ldr sp, =0x84000000 用于設置棧指針。野火i.MX6ULL開發板標配512M的DDR內存,裸機開發用不了這么多。程序中我們將棧地址設置到DDR的64M地址處。 這個值也可以根據需要自行定義。
b main 只用跳轉指令跳轉到main函數中執行。
/***********************第四部分*********************/ ldr sp, =0x84000000 //設置棧地址64M b main //跳轉到main函數
第五部分
b loop 是“無返回”的跳轉指令。正常情況下,不會執行第五部分代碼。
/***********************第五部分*******************/ /*進入死循環*/ loop: b loop
十一、編寫鏈接腳本
寫好的代碼(無論是匯編還是C語言)都要經過編譯、匯編、鏈接等步驟生成二進制文件或者可供下載的文件。在編譯階編譯器會對每個源文件進行語法檢查并生成對應的匯編語言,匯編是將匯編文件轉化為機器碼。
上一篇:解決方法:編譯IMX6ULL裸機串口程序提示錯誤arm-none-eabi-ld: cannot find -lgcc: 沒有那個文件或目
下一篇:IMX6ULL學習筆記(18)——GPIO中斷
推薦閱讀最新更新時間:2025-07-02 23:57




設計資源 培訓 開發板 精華推薦
- MC33174DR2G 有源高 Q 陷波濾波器的典型應用
- 使用 Analog Devices 的 LTC1159CG-3.3 的參考設計
- LTC1727IS8-5、3.3V 和 5V 雙電源監視器的典型應用
- 使用 LT6202 將 ±10V 雙極性信號轉換為 0V 至 5V 輸入信號到 LTC2370CMS-16 的典型應用
- LT3724 的典型應用 - 高電壓、電流模式開關穩壓控制器
- TS9010ACX5 RF 150mA, 1.5V CMOS LDO with Enable 典型應用電路
- L5150GJ 5 V 低壓差穩壓器的典型應用
- MPC86XADS、XPC8xx 參考板,基于 XPC860EN MPU PowerQUICC MPC8xx 處理器
- OP249GSZ-REEL 失調調整的典型應用電路,用于同相放大器配置
- 使用 Microchip Technology 的 MAX3221ECAE 的參考設計
- 納祥科技2W 24位數字功放NX4920,可用于AI語音播報、WIFI播放器
- 常用解調器的定義和工作原理
- 從性能與網絡傳輸出發,講講鐵威馬MAX系列為什么一騎絕塵
- 惠普選中Hailo下一代人工智能加速器,革新零售業與酒店業運營模式
- 跨國商務溝通困局破解之道:時空壺 W4Pro 全場景應用解析
- 從矢量降噪到雙向同傳,時空壺 W4Pro 如何重構 AI 同傳技術標準?
- LoRa+NB-IoT雙模融合,地下車庫信號盲區電梯場景等的冗余通信
- LoRa與UWB的“定位之戰”,成本敏感場景高精度需求的場景切割
- 時空壺X1再升級:引領AI同傳新時代,革新演講翻譯體驗
- ARXML 規則下 ECU 總線通訊與 ADTF 測試方案