STMicroelectronics' implementation of an I2S driver, also including DMA support.

Dependents:   temp X_NUCLEO_CCA01M1 X_NUCLEO_CCA01M1 X_NUCLEO_CCA02M1

Platform compatibility

This driver has been designed to support a wide range of the Nucleo F4 Family of platforms and MCUs, but not all members of this family support I2S and/or some of the members might require slight modifications to the sources of this driver in order to make it work on those.

This driver has for now been tested only with the following platforms:

Revision:
5:74da3773bf43
Parent:
1:f90318e0923b
Child:
7:e9105ae127ad
--- a/targets/TARGET_STM/stm_i2s_api.c	Tue Nov 29 14:43:26 2016 +0100
+++ b/targets/TARGET_STM/stm_i2s_api.c	Wed Dec 14 09:05:34 2016 +0100
@@ -11,6 +11,7 @@
 #include "cmsis.h"
 #include "pinmap.h"
 #include "PeripheralPins.h"
+#include "StmI2sPeripheralPins.h"
 
 // #define DEBUG_STDIO 1 // betzw - TODO: temporarily enable debug printfs
 
@@ -41,8 +42,7 @@
 static I2S_HandleTypeDef I2sHandle[I2S_NUM];
 static DMA_HandleTypeDef DMaHandles[I2S_NUM][NUM_OF_DIRECTIONS];
 
-static void init_i2s(i2s_t *obj)
-{
+static void init_i2s(i2s_t *obj) {
     I2S_HandleTypeDef *handle = &I2sHandle[obj->i2s.module];
 
     __HAL_I2S_DISABLE(handle);
@@ -50,8 +50,7 @@
     __HAL_I2S_ENABLE(handle);
 }
 
-static void init_dmas(i2s_t *obj)
-{
+static void init_dmas(i2s_t *obj) {
     DMA_HandleTypeDef *primary_handle = NULL;
     DMA_HandleTypeDef *secondary_handle = NULL;
     DMA_HandleTypeDef *hdmatx = NULL;
@@ -136,20 +135,20 @@
     DMA_HandleTypeDef *secondary_handle = NULL;
 
     // DMA initialization & configuration
-    dma_init();
+    stm_dma_init();
     obj->dma.dma[DMA_TX] = obj->dma.dma[DMA_RX] = NULL;
 
     switch(obj->dma.dma_direction) {
     case DMA_TX:
 	if(*use_tx) {
-	    obj->dma.dma[DMA_TX] = dma_channel_allocate(MAKE_CAP(obj->dma.dma_device, DMA_TX));
+	    obj->dma.dma[DMA_TX] = stm_dma_channel_allocate(MAKE_CAP(obj->dma.dma_device, DMA_TX));
 	    MBED_ASSERT(obj->dma.dma[DMA_TX] != DMA_ERROR_OUT_OF_CHANNELS);
 	}
 	break;
     case DMA_RX:
     default:
 	if(*use_rx) {
-	    obj->dma.dma[DMA_RX] = dma_channel_allocate(MAKE_CAP(obj->dma.dma_device, DMA_RX));
+	    obj->dma.dma[DMA_RX] = stm_dma_channel_allocate(MAKE_CAP(obj->dma.dma_device, DMA_RX));
 	    MBED_ASSERT(obj->dma.dma[DMA_RX] != DMA_ERROR_OUT_OF_CHANNELS);
 	}
 	break;
@@ -178,7 +177,7 @@
 	switch(obj->dma.dma_direction) {
 	case DMA_TX:
 	    if(*use_rx) {
-		obj->dma.dma[DMA_RX] = dma_channel_allocate(MAKE_CAP(obj->dma.dma_device, DMA_RX));
+		obj->dma.dma[DMA_RX] = stm_dma_channel_allocate(MAKE_CAP(obj->dma.dma_device, DMA_RX));
 		secondary_handle = &DMaHandles[obj->i2s.module][DMA_RX];
 		MBED_ASSERT(obj->dma.dma[DMA_RX] != DMA_ERROR_OUT_OF_CHANNELS);
 	    }
@@ -186,7 +185,7 @@
 	case DMA_RX:
 	default:
 	    if(*use_tx) {
-		obj->dma.dma[DMA_TX] = dma_channel_allocate(MAKE_CAP(obj->dma.dma_device, DMA_TX));
+		obj->dma.dma[DMA_TX] = stm_dma_channel_allocate(MAKE_CAP(obj->dma.dma_device, DMA_TX));
 		secondary_handle = &DMaHandles[obj->i2s.module][DMA_TX];
 		MBED_ASSERT(obj->dma.dma[DMA_TX] != DMA_ERROR_OUT_OF_CHANNELS);
 	    }
@@ -236,12 +235,11 @@
     NVIC_DisableIRQ(stream->dma_stream_irq);
 
     // free channel
-    dma_channel_free((void*)stream);
+    stm_dma_channel_free((void*)stream);
     obj->dma.dma[direction] = NULL;
 }
 
-void i2s_init(i2s_t *obj, PinName data, PinName sclk, PinName wsel, PinName fdpx, PinName mclk, i2s_mode_t mode)
-{
+void i2s_init(i2s_t *obj, PinName data, PinName sclk, PinName wsel, PinName fdpx, PinName mclk, i2s_mode_t mode) {
     uint8_t dma_dev = 0, dma_direction = 0;
 
     // Determine the I2S/SPI to use
@@ -360,8 +358,7 @@
     init_i2s(obj);
 }
 
-void i2s_free(i2s_t *obj)
-{
+void i2s_free(i2s_t *obj) {
     // Reset I2S and disable clock
     switch(obj->i2s.module) {
 #if defined(I2S1ext_BASE)
@@ -417,8 +414,7 @@
     DEBUG_PRINTF("I2S%u: Free\n", obj->i2s.module+1);
 }
 
-void i2s_format(i2s_t *obj, int dbits, int fbits, int polarity)
-{
+void i2s_format(i2s_t *obj, int dbits, int fbits, int polarity) {
     I2S_HandleTypeDef *handle = &I2sHandle[obj->i2s.module];
 
     // Save new values
@@ -448,8 +444,7 @@
     init_i2s(obj);
 }
 
-void i2s_set_mode(i2s_t *obj, i2s_mode_t mode)
-{
+void i2s_set_mode(i2s_t *obj, i2s_mode_t mode) {
     uint8_t dma_direction;
     I2S_HandleTypeDef *handle = &I2sHandle[obj->i2s.module];
 
@@ -464,8 +459,7 @@
     init_i2s(obj);
 }
 
-void i2s_set_protocol(i2s_t *obj, i2s_bitorder_t protocol)
-{
+void i2s_set_protocol(i2s_t *obj, i2s_bitorder_t protocol) {
     I2S_HandleTypeDef *handle = &I2sHandle[obj->i2s.module];
 
     switch (protocol) {
@@ -493,8 +487,7 @@
     init_i2s(obj);
 }
 
-void i2s_audio_frequency(i2s_t *obj, uint32_t hz)
-{
+void i2s_audio_frequency(i2s_t *obj, uint32_t hz) {
     I2S_HandleTypeDef *handle = &I2sHandle[obj->i2s.module];
 
     if (IS_I2S_AUDIO_FREQ(hz) && (hz != I2S_AUDIOFREQ_DEFAULT)) {
@@ -511,8 +504,7 @@
     init_i2s(obj);
 }
 
-uint8_t i2s_get_module(i2s_t *obj)
-{
+uint8_t i2s_get_module(i2s_t *obj) {
     return obj->i2s.module;
 }
 
@@ -621,8 +613,7 @@
     }
 }
 
-uint32_t i2s_irq_handler_asynch(i2s_t *obj, uint8_t direction)
-{
+uint32_t i2s_irq_handler_asynch(i2s_t *obj, uint8_t direction) {
     direction = (direction == I2S_TX_EVENT) ? DMA_TX : DMA_RX;
 
     // use the right instance
@@ -672,7 +663,7 @@
 	    DEBUG_PRINTF("I2S%u: RxXferCount: %u\n", obj->i2s.module+1, i2s_handle->RxXferCount);
 	}
     }
-    /* no break */
+	/* no break */
 
     case HAL_I2S_STATE_BUSY_TX:
     case HAL_I2S_STATE_BUSY_RX:
@@ -735,8 +726,7 @@
     return (event & (obj->i2s.event | I2S_EVENT_INTERNAL_TRANSFER_COMPLETE));
 }
 
-uint8_t i2s_active(i2s_t *obj)
-{
+uint8_t i2s_active(i2s_t *obj) {
     I2S_HandleTypeDef *handle = &I2sHandle[obj->i2s.module];
     HAL_I2S_StateTypeDef state = HAL_I2S_GetState(handle);
 
@@ -750,8 +740,7 @@
     }
 }
 
-void i2s_abort_asynch(i2s_t *obj)
-{
+void i2s_abort_asynch(i2s_t *obj) {
     I2S_HandleTypeDef *i2s_handle = &I2sHandle[obj->i2s.module];
 
     // Stop transfer