I2Sのサンプリング周波数が192kHzの場合、周期 T = 1 / f ≒ 5.21us、L/Rの2chだとその半分の2.60usがリアルタイムな計算に使える時間となります。
前回、
FPUを使って算術関数の実行速度を測定しました。G431KBの場合、expf()1000回で1msだったので、1回あたり1usとなります。リアルタイムに計算する場合せいぜいexpf()2回が限度となります。
さらに、I2SのDMA転送が完了するまでメモリの内容はいじれませんので、転送が完了するまでの待ち時間が発生します。転送完了の割り込みが発生してから次の転送開始までどれぐらいの猶予があるか測定しました。
ソースコード(main.cに追加)
/* USER CODE BEGIN PV */
int32_t data[2] = { 0 };
int32_t tx_buffer[2] = { 0 };
/* USER CODE END PV */
<中略>
int main(void)
{
/* USER CODE BEGIN 2 */
HAL_I2S_Transmit_DMA(&hi2s2, (uint16_t *)tx_buffer, 2);
/* USER CODE END 2 */
<中略>
/* USER CODE BEGIN 4 */
static int32_t swap16(int32_t x)
{
return ((uint32_t)x << 16) | ((uint32_t)x >> 16);
}
void HAL_I2S_TxHalfCpltCallback(I2S_HandleTypeDef *hi2s)
{
HAL_GPIO_WritePin(CK_HALF_CPLT_GPIO_Port, CK_HALF_CPLT_Pin, GPIO_PIN_SET);
tx_buffer[0] = swap16(data[0]++);
HAL_GPIO_WritePin(CK_HALF_CPLT_GPIO_Port, CK_HALF_CPLT_Pin, GPIO_PIN_RESET);
}
void HAL_I2S_TxCpltCallback(I2S_HandleTypeDef *hi2s)
{
HAL_GPIO_WritePin(CK_CPLT_GPIO_Port, CK_CPLT_Pin, GPIO_PIN_SET);
tx_buffer[1] = swap16(data[1]--);
HAL_GPIO_WritePin(CK_CPLT_GPIO_Port, CK_CPLT_Pin, GPIO_PIN_RESET);
}
/* USER CODE END 4 */
F303K8はSTM32CubeIDEではI2Sの設定ができませんので、F446RE、F767ZI、G431KBで測定しました。
F446REの設定
MXの設定
Pinout & Configuration
System Core
GPIO
PC10
Maximum output speed: Very High
User Label: CK_HALF_CPLT
PC12
Maximum output speed: Very High
User Label: CK_CPLT
Multimedia
I2S2
Mode: Half-Duplex Master
Parameter Settings
Data and Frame Format: 32 Bits Data on 32 Bits Frame
Selected Audio Frequency: 192KHz
Real Audio Frequency: 195.312Khz
DMA Settings
SPI2_TX
Mode: Circular
Data Width: Half Word / Half Word
Clock Configuration
HSE->PLL HCLK: 180MHz
プロジェクトの設定
Project - Properties
C/C++ Build
Settings
Configuraion: Release
Tool Settings
MCU GCC Compiler
Optimization
Optimizaion level: Optimize for speed (-Ofast)
F767ZIの設定
Nucleo-F767ZIはデフォルトでETHが有効化されていて実行時にエラーが発生するので、MXで無効化します。
MXの設定
Pinout & Configuration
System Core
GPIO
PB10
Maximum output speed: Very High
User Label: CK_CPLT
PB11
Maximum output speed: Very High
User Label: CK_HALF_CPLT
Connectivity
ETH
Mode: Disable
Multimedia
I2S2
Mode: Half-Duplex Master
Parameter Settings
Data and Frame Format: 32 Bits Data on 32 Bits Frame
Selected Audio Frequency: 192KHz
Real Audio Frequency: 187.5Khz
DMA Settings
SPI2_TX
Mode: Circular
Data Width: Half Word / Half Word
Clock Configuration
HSE->PLL HCLK: 216MHz
プロジェクトの設定
Project - Properties
C/C++ Build
Settings
Configuraion: Release
Tool Settings
MCU GCC Compiler
Optimization
Optimizaion level: Optimize for speed (-Ofast)
G431GBの設定
Nucleo-G431KBはPF0、PF1を有効にするためにボード上のはんだジャンパSB8、SB11をブリッジしました。
Pinout & Configuration
System Core
GPIO
PA12
Maximum output speed: Very High
User Label: CK_HALF_CPLT
PB0
Maximum output speed: Very High
User Label: CK_CPLT
Multimedia
I2S2
Mode: Half-Duplex Master
Parameter Settings
Data and Frame Format: 32 Bits Data on 32 Bits Frame
Selected Audio Frequency: 192KHz
Real Audio Frequency: 189.732dKhz
DMA Settings
SPI2_TX
Mode: Circular
Data Width: Half Word / Half Word
Clock Configuration
HSI->PLL HCLK: 170MHz
プロジェクトの設定
Project - Properties
C/C++ Build
Settings
Configuraion: Release
Tool Settings
MCU GCC Compiler
Optimization
Optimizaion level: Optimize for speed (-Ofast)
各Nucleoボードのデフォルトの設定で、I2Sを初期化すると割り当てられるピンは以下の通りです。
Board
|
I2S2_CK
|
I2S2_WS
|
I2S2_SD
|
F446RE
|
PB10
|
PB12
|
PC1
|
F767ZI
|
PD3
|
PB12
|
PC3
|
G431KB
|
PF1
|
PF0
|
PA11
|
実行結果
LchのDMA転送が完了したときに発生する割り込みHAL_I2S_TxHalfCpltCallback()から、RchのI2S通信が開始するWSがHighになる時点までの時間を計測しました。
WSがHighになってRchの通信が開始してからも、しばらくはLchのバッファをいじれるかもしれませんが、よくわかっていないので考慮にいれていません。少なくともRchのCPLTが呼び出されて、MPU本体に制御が戻る前にLchの仕事を完了させないといけません。
F446RE
F767ZI
G431KB
Board
|
猶予時間(us)
|
F446RE
|
1.59
|
F767ZI
|
1.1
|
G431KB
|
1.89
|
このテストもF767ZIの成績が芳しくありません。
おおよその目安として、192kHz/2chでI2S出力する場合、リアルタイムに算術関数を1回実行するが精一杯というところでしょうか。