恩智浦的i.MX RT1010是跨界處理器產品,作為i.MX RT跨界MCU系列的一個新的切入點,i.MX RT1010是成本最低的LQFP封裝方式與i.MX RT系列產品一貫的高性能和易用性的結合產物。
i.MX RT1010處理器基於ARM Cortex-M7平台,它具有較高的CPU性能和最佳的實時響應,並具有豐富的外設資源。其中FlexIO是一個高度可配置的模塊,能夠模擬多種不同的通信協議,包括UART, I2C, SPI, I2S等。本文介紹如何利用i.MX RT1010的FlexIO外設來模擬I2S總線。
一、硬件平台
本應用筆記主要介紹如何使用FlexIO模塊模擬I2S接口,實現音頻數據的采集,傳輸並播放。使用FlexIO模塊模擬I2S總線信號,可以代替傳統的I2S或者SAI外設來傳輸音頻數據,非常節省MCU的片上資源。整個demo基於i.MX RT1010 EVK板子進行開發,如下所示。

i.MX RT1010利用板載麥克風采集音頻數據到sram緩沖區中進行處理,然后使用模擬的I2S接口將音頻數據發送到音頻播放設備,所有音頻數據的處理都圍繞板上的編解碼芯片WM8960實現。另外,為了能夠成功演示該demo,需要對i.MX RT1010 EVK板子進行如下操作和改動,整體實物圖也如下所示。
-
音頻揚聲器的數字接口插入RT1010 EVK板的J11端口。
-
將ISP撥碼開關SW8更改為0b0010模式。
-
將J1-3和J1-4引腳用短路帽連接,將USB線插到板上的J9口進行供電。
-
去掉iMX RT1010 EVK板上的R85,R87,R88,R20這幾個電阻。
-
FLEXIO需要用到的具體引腳和U10的對應連接關系如下:
引腳名稱 位置 位置 FlexIO引腳號 SDA_RX J54-2 U10-16 FlexIO03 SDA_TX J26-8 U10-14 FlexIO26 SYNC J26-6 U10-13 FlexIO22 BCLK J26-4 U10-12 FlexIO21
二、 應用
2.1 系統架構
在此應用中,demo整個架構和I2S接口的連接關系如圖所示。i.MX RT1010作為I2S的從設備,利用FlexIO模擬了四根引腳,它們分別是I2S接口的SDA_RX、SDA_TX、FSYNC(WS)以及BLCK。WM8960編解碼器作為I2S的主設備,從MIC接收音頻信號,然后通過SDA_RX引腳將音頻數據傳輸到RT1010。RT1010將接收的音頻數據處理后,再通過SDA_TX引腳發送給WM8960,WM8960將PCM數據轉成模擬信號交由揚聲器播放。此外,RT1010通過I2C接口對WM8960進行初始化配置操作。
2.2 時鍾及采樣頻率配置
與MCU做為I2S主機不同的是,當MCU作為I2S從機時,FSYNC和BLCK信號是由WM8960產生的,因此第一步要把WM8960配置成master模式。WM8960的MCLK時鍾可以由RT1010提供,也可以由WM8960提供。本應用中,我們利用RT1010產生MCLK信號比較方便,並把MCLK配置為6.144MHz。
常見的I2S采樣頻率通常有兩組,如下所示。 本應用中,I2S采樣頻率配置為16kHz,同樣WM8960的采樣頻率也需要被配置為16kHz。一旦I2S的采樣頻率確定了,那FSYNC信號的頻率也就確定了,也為16kHz。
Typical Sample Frequency (Hz) | Typical Sample Frequency (Hz) |
---|---|
11025 | 8000 |
22050 | 16000 |
44100 | 24000 |
-------- | 32000 |
-------- | 48000 |
為了能夠模擬I2S接口作為slave模式,FlexIO的時鍾配置是有一定要求的,它必須是采樣頻率的某個倍數,這樣FlexIO的定時器才能匹配這個頻率。在本應用中,FlexIO時鍾被配置為6.144MHz,FlexIO模擬的I2S接口基於這個時鍾來實現。
下一步,需要對WM8960進行一系列配置,使其從板載MIC采集的音頻信號在傳輸給RT1010時,是16KHz,32bit的立體聲(左右聲道)音頻數據。
接着,我們需要計算並配置FlexIO的各個引腳時鍾,BCLK時鍾信號是由WM8960產生的,MCLK作為WM8960的參考時鍾,經過分頻得到BCLK時鍾,過程如下:
- FSYNC = 16KHz
- MCLK = 6.144MHz
- BCLK = FSYNC * 聲道數 * 聲道位寬 = 16KHz * 2 * 32 = 1.024MHz
- BCLK_DIV (BLCK分頻系數) = MCLK / BCLK = 6.144MHz / 1.024MHz = 6
此外,在本應用中還需要將I2S模式配置為經典I2S模式。有讀者如果對I2S協議不清楚,可以參考筆者的另一篇博客i.MX RT600之I2S外設介紹及應用。
下面給出了WM8960編解碼器的部分配置代碼:
wm8960_config_t wm8960Config = {
.i2cConfig = {.codecI2CInstance
= BOARD_CODEC_I2C_INSTANCE,.codecI2CSourceClock = BOARD_CODEC_I2C_CLOCK_FREQ},
.route = kWM8960_RoutePlaybackandRecord,
.rightInputSource = kWM8960_InputDifferentialMicInput2,
.playSource = kWM8960_PlaySourceDAC,
.slaveAddress = WM8960_I2C_ADDR,
.bus = kWM8960_BusI2S,
.format = {.mclk_HZ = 6144000U,
.sampleRate = kWM8960_AudioSampleRate16KHz,
.bitWidth = kWM8960_AudioBitWidth32bit},
.master_slave = true,
};
codec_config_t boardCodecConfig = {
.codecDevType = kCODEC_WM8960,
.codecDevConfig = &wm8960Config
};
/* Init codec */
CODEC_Init(&codecHandle, &boardCodecConfig);
2.3 FlexIO配置
FlexIO是一個具有多種功能,高度可配置的模塊,具有以下特點:
- 支持多種串行/並行通信協議的仿真,例如UART,I2C,SPI,I2S等。
- 靈活的16位定時器,支持多種觸發,復位,使能和禁止條件。
- 可編程邏輯塊,允許在片上實現數字邏輯功能以及內部和外部模塊的可配置交互。
- 可編程狀態機,用於不依賴CPU而實現基本的系統控制功能。
在i.MX RT1010上,FLEXIO共有27個引腳。本應用一共使用了4個FlexIO引腳(FlexIO03引腳,FlexIO21引腳,FlexIO22引腳,FlexIO26引腳)分別模擬I2S接口的SDA_RX引腳,BCLK引腳,FSYNC引腳和SDA_TX引腳。 下圖顯示了FlexIO模擬I2S接口的內部連接。 Timer0和定時Timer2連接的FlexIO引腳分別用於產生BCLK信號和FSYNC信號,而SHIFTER0和SHIFTER2的FlexIO引腳分別用於產生SDA_TX信號和SDA_RX信號。下面分別介紹SHIFTER和Timer使用方法和配置。
通過配置SHIFTCTL寄存器,可以將SHIFTER配置成6種模式,本應用場景中只需要關注Transmit模式和Receive模式就行。
先對SHIFTER0進行配置。將SHIFTER0配置為Transmit模式,SHIFER0在移位時鍾的上降沿將SHIFERBUF0中的數據從TX引腳輸出。SHIFTER2被配置為Receive模式,同樣SHIFER2在移位時鍾的下降沿從RX引腳上獲取數據並放入SHIFERBUF2。當數據從SHIFTER加載到SHIFTBUF寄存器中或數據從SHIFTBUF寄存器加載到SHIFTER中時,如果已經將SHIFTER狀態標志位(SHIFTSDEN SSDE)置1,就可以產生一個DMA請求。整個 SHIFTER的微體系結構如圖所示,它充分展示了SHIFER中各個模塊之間的關系以及IO引腳輸入輸出的關系。
下面需要對Timer0和Timer2進行配置。
當Timer2檢測到FSYNC的上升沿時使能,當其檢測到trigger事件的下降沿時禁用。Timer0的使能發生在BLCK的上升沿以及Timer2的trigger事件檢測為高電平時,Timer0的關閉發生在其自身的比較事件產生時。此外,Timer0和Timer2的時鍾狀態需要被初始化為邏輯1。Timer2的時鍾模式需要被配置為16位計數模式,其比較事件產生的值設置為0,並使用FSYNC引腳的輸入作為遞減量,使用BCLK引腳的輸入作為trigger事件。Timer0的時鍾模式需要被配置為16位計數器,並使用BCLK引腳的輸入作為遞減量。 在此應用中,Timer2的比較事件產生的值設置為127(32 * 4-1),這是根據64bit一幀的音頻數據位寬長度計算得到的。
下面給除了詳細的寄存器配置:
- FlEXIO01.SHIFTCTL [0] = 0x00031A02
- FlEXIO01.SHIFTCTL [2] = 0x00800301
- FlEXIO01.TIMCTL [0] = 0x0B401583
- FlEXIO01.TIMCTL [2] = 0x2A401683
- FlEXIO01.TIMCFG [0] = 0x00202500
- FlEXIO01.TIMCFG [2] = 0x00206400
- FlEXIO01.TIMCMP [0] = 0x0000007F
- FlEXIO01.TIMCMP [2] = 0x00000000
到這里,FlexIO用於模擬I2S接口的基本配置就介紹完畢,接下來還需要介紹音頻數據的處理機制。
2.4 音頻流處理
MCU在同時接收和發送PCM數據並進行播放的應用場景中,容易出現播放音樂卡頓的情況,為了避免出現這種卡頓,一個好的傳輸機制是必不可少的,下圖就給出了一種處理PCM數據的思路。
每當FlexIO中的SHIFTER有DMA請求產生時,應立即從SHIFTBUF讀取或寫入音頻數據。下圖中兩個緩沖區用於PCM數據的發送和接收,這兩個緩沖區構成了ping-pang buffer。PCM數據幀的位寬為64位(左通道和右通道),每個緩沖區被設置為256bit,即存放4幀PCM數據, 每當一個緩沖區中的PCM數據接收滿或發送時,下一個緩沖區將立即開始接收或發送。

2.5 注意事項
在利用FlexIO模擬I2S時,需要注意兩點:
-
由於FlexIO同步延遲,當FlexIO用來模擬I2S從設備時,串行數據的輸出有效時間是FlexIO時鍾周期的2.5倍。 因此,I2S的BCLK最大時鍾頻率應當是FlexIO時鍾頻率的六分之一。
-
FlexIO是一個功能強大,非常靈活的模塊,除了本文給出的Timer和SHIFTER的配置外,讀者也可以利用其它配置模擬出I2S接口。
至此,i.MX RT1010之FlexIO模擬I2S外設介紹完畢。