I am using Sparkfun´s MAX98357A breakout board. The MAX98357 does not require an MCLK, so this part of the setup is not included.
1. Enable I2S in halconf.h
Code: Select all
/**
* @brief Enables the I2S subsystem.
*/
#if !defined(HAL_USE_I2S) || defined(__DOXYGEN__)
#define HAL_USE_I2S TRUE
#endif
2. Assign a SPI channel and a DMA resource. Note that you need to choose a suitable DMA channel, "Summary of DMA1 requests for each channel" in the reference manual tells you which one. I chose SPI2 and therefore DMA1, channel 5.
mcuconf.h
Code: Select all
/*
* SPI driver system settings.
*/
#define STM32_SPI_USE_SPI1 TRUE
#define STM32_SPI_USE_SPI2 FALSE
#define STM32_I2S_USE_SPI1 FALSE
#define STM32_I2S_USE_SPI2 TRUE
#define STM32_I2S_SPI2_MODE STM32_I2S_MODE_MASTER | STM32_I2S_MODE_TX
#define STM32_SPI_SPI1_DMA_PRIORITY 1
#define STM32_SPI_SPI2_DMA_PRIORITY 1
#define STM32_SPI_SPI1_IRQ_PRIORITY 10
#define STM32_SPI_SPI2_IRQ_PRIORITY 10
#define STM32_I2S_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5)
#define STM32_I2S_SPI2_RX_DMA_STREAM 0
#define STM32_SPI_DMA_ERROR_HOOK(spip) osalSysHalt("DMA failure")
Note that you actually need to add code to mcuconf.h (I was used to only modifying some TRUE/FALSE entries).
3. Configure the outputs in board.h. On the STM32L152, SPI is AF5, and SPI2 can be mapped to PB12 (LRCLK), PB13 (BCLK), PB15 (data).
Code: Select all
#define GPIOB_I2S_LRCK 12U
#define GPIOB_I2S_CLK 13U
#define GPIOB_I2S_DATA 15U
...
#define VAL_GPIOB_MODER ... | \
PIN_MODE_ALTERNATE(GPIOB_I2S_LRCK) | \
PIN_MODE_ALTERNATE(GPIOB_I2S_CLK) | \
PIN_MODE_INPUT(GPIOB_PIN14) | \
PIN_MODE_ALTERNATE(GPIOB_I2S_DATA))
...
#define VAL_GPIOB_AFRH .... | \
PIN_AFIO_AF(GPIOB_I2S_LRCK, 5U) | \
PIN_AFIO_AF(GPIOB_I2S_CLK, 5U) | \
PIN_AFIO_AF(GPIOB_PIN14, 0U) | \
PIN_AFIO_AF(GPIOB_I2S_DATA, 5U))
Set up the I2S configuration. It is important to set IS2DIV (lowest 8 bits of I2SPR) to a proper value, as it defines the clock. I my case, 0x10 resulted in about 32 kHz on LRCLK or about 1 MHz on BCLK. This caused the MAX98357 to finally produce some noise.
Code: Select all
uint8_t tx_bfr[512];
void i2s_callback(I2SDriver *i2sp) {
return;
}
int main(void) {
halInit();
chSysInit();
for (uint16_t k=0; k < 512; k++) {
tx_bfr[k] = rx_bfr[k] = (uint8_t)k;
}
I2SConfig i2s_config = {
.tx_buffer = tx_bfr,
.rx_buffer = 0,
.size = sizeof(tx_bfr) >> 1,
.end_cb = i2s_callback,
.i2spr = 0x10
};
i2sStart(&I2SD2,&i2s_config);
i2sStartExchange(&I2SD2);
In the hope that it will help someone,
Max