Il y avait des problèmes dans la libraire...
Fork of ST_I2S by
Diff: targets/TARGET_STM/stm_i2s_api.c
- Revision:
- 2:0c9ce59aee25
- Parent:
- 1:f90318e0923b
- Child:
- 3:25de898f5354
--- a/targets/TARGET_STM/stm_i2s_api.c Tue Nov 29 14:43:26 2016 +0100 +++ b/targets/TARGET_STM/stm_i2s_api.c Tue Dec 13 18:09:02 2016 +0100 @@ -11,8 +11,9 @@ #include "cmsis.h" #include "pinmap.h" #include "PeripheralPins.h" +#include "StmI2sPeripheralPins.h" -// #define DEBUG_STDIO 1 // betzw - TODO: temporarily enable debug printfs +//#define DEBUG_STDIO 1 // betzw - TODO: temporarily enable debug printfs #ifndef DEBUG_STDIO # define DEBUG_STDIO 0 @@ -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,83 +50,82 @@ __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; switch(obj->dma.dma_direction) { - case DMA_TX: - if(obj->dma.dma[DMA_TX] != NULL) { - hdmatx = primary_handle = &DMaHandles[obj->i2s.module][DMA_TX]; - } - if(obj->dma.dma[DMA_RX] != NULL) { - secondary_handle = &DMaHandles[obj->i2s.module][DMA_RX]; - } - break; - case DMA_RX: - default: - if(obj->dma.dma[DMA_RX] != NULL) { - primary_handle = &DMaHandles[obj->i2s.module][DMA_RX]; - } - if(obj->dma.dma[DMA_TX] != NULL) { - hdmatx = secondary_handle = &DMaHandles[obj->i2s.module][DMA_TX]; - } - break; + case DMA_TX: + if(obj->dma.dma[DMA_TX] != NULL) { + hdmatx = primary_handle = &DMaHandles[obj->i2s.module][DMA_TX]; + } + if(obj->dma.dma[DMA_RX] != NULL) { + secondary_handle = &DMaHandles[obj->i2s.module][DMA_RX]; + } + break; + case DMA_RX: + default: + if(obj->dma.dma[DMA_RX] != NULL) { + primary_handle = &DMaHandles[obj->i2s.module][DMA_RX]; + } + if(obj->dma.dma[DMA_TX] != NULL) { + hdmatx = secondary_handle = &DMaHandles[obj->i2s.module][DMA_TX]; + } + break; } if(primary_handle != NULL) { - __HAL_DMA_DISABLE(primary_handle); - HAL_DMA_Init(primary_handle); + __HAL_DMA_DISABLE(primary_handle); + HAL_DMA_Init(primary_handle); - if(hdmatx == primary_handle) { - __HAL_LINKDMA(&I2sHandle[obj->i2s.module], hdmatx, *primary_handle); - } else { - __HAL_LINKDMA(&I2sHandle[obj->i2s.module], hdmarx, *primary_handle); - } + if(hdmatx == primary_handle) { + __HAL_LINKDMA(&I2sHandle[obj->i2s.module], hdmatx, *primary_handle); + } else { + __HAL_LINKDMA(&I2sHandle[obj->i2s.module], hdmarx, *primary_handle); + } } if(secondary_handle != NULL) { - __HAL_DMA_DISABLE(secondary_handle); - HAL_DMA_Init(secondary_handle); + __HAL_DMA_DISABLE(secondary_handle); + HAL_DMA_Init(secondary_handle); - if(hdmatx == secondary_handle) { - __HAL_LINKDMA(&I2sHandle[obj->i2s.module], hdmatx, *secondary_handle); - } else { - __HAL_LINKDMA(&I2sHandle[obj->i2s.module], hdmarx, *secondary_handle); - } + if(hdmatx == secondary_handle) { + __HAL_LINKDMA(&I2sHandle[obj->i2s.module], hdmatx, *secondary_handle); + } else { + __HAL_LINKDMA(&I2sHandle[obj->i2s.module], hdmarx, *secondary_handle); + } } } static inline uint32_t i2s_get_mode(i2s_mode_t mode, uint8_t *direction) { switch(mode) { - case SLAVE_TX: - *direction = DMA_TX; - return I2S_MODE_SLAVE_TX; - case SLAVE_RX: - *direction = DMA_RX; - return I2S_MODE_SLAVE_RX; - case MASTER_TX: - *direction = DMA_TX; - return I2S_MODE_MASTER_TX; - case MASTER_RX: - default: - *direction = DMA_RX; - return I2S_MODE_MASTER_RX; + case SLAVE_TX: + *direction = DMA_TX; + return I2S_MODE_SLAVE_TX; + case SLAVE_RX: + *direction = DMA_RX; + return I2S_MODE_SLAVE_RX; + case MASTER_TX: + *direction = DMA_TX; + return I2S_MODE_MASTER_TX; + case MASTER_RX: + default: + *direction = DMA_RX; + return I2S_MODE_MASTER_RX; } } static inline uint32_t i2s_get_priority(i2s_dma_prio_t priority) { switch(priority) { - case LOW: - return DMA_PRIORITY_LOW; - case URGENT: - return DMA_PRIORITY_VERY_HIGH; - case HIGH: - return DMA_PRIORITY_HIGH; - default: - return DMA_PRIORITY_MEDIUM; + case LOW: + return DMA_PRIORITY_LOW; + case URGENT: + return DMA_PRIORITY_VERY_HIGH; + case HIGH: + return DMA_PRIORITY_HIGH; + default: + return DMA_PRIORITY_MEDIUM; } } @@ -136,82 +135,82 @@ 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)); - 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)); - MBED_ASSERT(obj->dma.dma[DMA_RX] != DMA_ERROR_OUT_OF_CHANNELS); - } - break; + case DMA_TX: + if(*use_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] = 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; } // Primary DMA configuration if(obj->dma.dma[obj->dma.dma_direction] != NULL) { - primary_handle->Instance = obj->dma.dma[obj->dma.dma_direction]->dma_stream; - primary_handle->Init.Channel = obj->dma.dma[obj->dma.dma_direction]->channel_nr; - primary_handle->Init.Direction = (obj->dma.dma_direction == DMA_TX) ? - DMA_MEMORY_TO_PERIPH : DMA_PERIPH_TO_MEMORY; - primary_handle->Init.FIFOMode = DMA_FIFOMODE_DISABLE; - primary_handle->Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; - primary_handle->Init.MemBurst = DMA_MBURST_SINGLE; - primary_handle->Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; - primary_handle->Init.MemInc = DMA_MINC_ENABLE; - primary_handle->Init.Mode = (circular ? DMA_CIRCULAR : DMA_NORMAL); - primary_handle->Init.PeriphBurst = DMA_PBURST_SINGLE; - primary_handle->Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; - primary_handle->Init.PeriphInc = DMA_PINC_DISABLE; - primary_handle->Init.Priority = i2s_get_priority(prio); + primary_handle->Instance = obj->dma.dma[obj->dma.dma_direction]->dma_stream; + primary_handle->Init.Channel = obj->dma.dma[obj->dma.dma_direction]->channel_nr; + primary_handle->Init.Direction = (obj->dma.dma_direction == DMA_TX) ? + DMA_MEMORY_TO_PERIPH : DMA_PERIPH_TO_MEMORY; + primary_handle->Init.FIFOMode = DMA_FIFOMODE_DISABLE; + primary_handle->Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; + primary_handle->Init.MemBurst = DMA_MBURST_SINGLE; + primary_handle->Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; + primary_handle->Init.MemInc = DMA_MINC_ENABLE; + primary_handle->Init.Mode = (circular ? DMA_CIRCULAR : DMA_NORMAL); + primary_handle->Init.PeriphBurst = DMA_PBURST_SINGLE; + primary_handle->Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; + primary_handle->Init.PeriphInc = DMA_PINC_DISABLE; + primary_handle->Init.Priority = i2s_get_priority(prio); } // Allocate secondary DMA channel (if full-duplex) if(obj->i2s.pin_fdpx != NC) { - 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)); - secondary_handle = &DMaHandles[obj->i2s.module][DMA_RX]; - MBED_ASSERT(obj->dma.dma[DMA_RX] != DMA_ERROR_OUT_OF_CHANNELS); - } - break; - case DMA_RX: - default: - if(*use_tx) { - obj->dma.dma[DMA_TX] = 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); - } - break; - } + switch(obj->dma.dma_direction) { + case DMA_TX: + if(*use_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); + } + break; + case DMA_RX: + default: + if(*use_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); + } + break; + } } // Secondary DMA configuration if(secondary_handle != NULL) { - uint8_t secondary_dma_direction = (obj->dma.dma_direction == DMA_TX) ? DMA_RX : DMA_TX; + uint8_t secondary_dma_direction = (obj->dma.dma_direction == DMA_TX) ? DMA_RX : DMA_TX; - secondary_handle->Instance = obj->dma.dma[secondary_dma_direction]->dma_stream; - secondary_handle->Init.Channel = obj->dma.dma[secondary_dma_direction]->channel_nr_fd; - secondary_handle->Init.Direction = (secondary_dma_direction == DMA_TX) ? - DMA_MEMORY_TO_PERIPH : DMA_PERIPH_TO_MEMORY; - secondary_handle->Init.FIFOMode = DMA_FIFOMODE_DISABLE; - secondary_handle->Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; - secondary_handle->Init.MemBurst = DMA_MBURST_SINGLE; - secondary_handle->Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; - secondary_handle->Init.MemInc = DMA_MINC_ENABLE; - secondary_handle->Init.Mode = (circular ? DMA_CIRCULAR : DMA_NORMAL); - secondary_handle->Init.PeriphBurst = DMA_PBURST_SINGLE; - secondary_handle->Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; - secondary_handle->Init.PeriphInc = DMA_PINC_DISABLE; - secondary_handle->Init.Priority = i2s_get_priority(prio); + secondary_handle->Instance = obj->dma.dma[secondary_dma_direction]->dma_stream; + secondary_handle->Init.Channel = obj->dma.dma[secondary_dma_direction]->channel_nr_fd; + secondary_handle->Init.Direction = (secondary_dma_direction == DMA_TX) ? + DMA_MEMORY_TO_PERIPH : DMA_PERIPH_TO_MEMORY; + secondary_handle->Init.FIFOMode = DMA_FIFOMODE_DISABLE; + secondary_handle->Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; + secondary_handle->Init.MemBurst = DMA_MBURST_SINGLE; + secondary_handle->Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; + secondary_handle->Init.MemInc = DMA_MINC_ENABLE; + secondary_handle->Init.Mode = (circular ? DMA_CIRCULAR : DMA_NORMAL); + secondary_handle->Init.PeriphBurst = DMA_PBURST_SINGLE; + secondary_handle->Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; + secondary_handle->Init.PeriphInc = DMA_PINC_DISABLE; + secondary_handle->Init.Priority = i2s_get_priority(prio); } if(obj->dma.dma[DMA_TX] == NULL) *use_tx = false; @@ -219,11 +218,12 @@ // don't do anything, if the buffers aren't valid if (!use_tx && !use_rx) { - DEBUG_PRINTF("I2S%u: No DMAs to init\n", obj->i2s.module+1); - return; + DEBUG_PRINTF(" I2S%u: No DMAs to init\r\n", obj->i2s.module + 1); + return; } - DEBUG_PRINTF("I2S%u: DMA(s) Init\n", obj->i2s.module+1); + DEBUG_PRINTF(" I2S%u: DMA(s) Init\r\n", obj->i2s.module + 1); + init_dmas(obj); } @@ -236,12 +236,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 @@ -318,90 +317,108 @@ obj->i2s.pin_fdpx = fdpx; obj->i2s.pin_mclk = mclk; - /* Configure PLLI2S */ + /* Configure PLLI2S */ static bool first_time = true; - if(first_time) { - RCC_PeriphCLKInitTypeDef PeriphClkInitStruct; + if (first_time) + { + RCC_PeriphCLKInitTypeDef PeriphClkInitStruct; - /* Get RTCClockSelection */ - HAL_RCCEx_GetPeriphCLKConfig(&PeriphClkInitStruct); + /* Get RTCClockSelection */ + HAL_RCCEx_GetPeriphCLKConfig(&PeriphClkInitStruct); - /* Set default configuration */ - PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_I2S; - PeriphClkInitStruct.PLLI2S.PLLI2SN = 271; // betzw: use values which are suggested in Table 90. of the - PeriphClkInitStruct.PLLI2S.PLLI2SR = 2; // reference manual for master clock enabled & 44100Hz + /* Set default configuration. Default frequency is 44100Hz. */ + PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_I2S; + PeriphClkInitStruct.PLLI2S.PLLI2SN = 271; // betzw: use values which are suggested in Table 91 of the + PeriphClkInitStruct.PLLI2S.PLLI2SR = 2; // reference manual for master clock enabled & 44100Hz. + #ifdef NDEBUG - HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct); + HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct); #else - HAL_StatusTypeDef ret = HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct); + HAL_StatusTypeDef ret = HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct); #endif - MBED_ASSERT(ret == HAL_OK); - first_time = false; + MBED_ASSERT(ret == HAL_OK); + + first_time = false; } - // initialize the handle for this master! + /* Initializing the handle for this master. */ I2S_HandleTypeDef *handle = &I2sHandle[obj->i2s.module]; handle->Instance = (SPI_TypeDef *)(instance); handle->Init.Mode = i2s_get_mode(mode, &dma_direction); handle->Init.Standard = I2S_STANDARD_PCM_SHORT; handle->Init.DataFormat = I2S_DATAFORMAT_16B; - handle->Init.MCLKOutput = I2S_MCLKOUTPUT_ENABLE; // betzw: always enable master clock to avoid frequency dis-alignment between I2S devices - handle->Init.AudioFreq = I2S_AUDIOFREQ_44K; handle->Init.CPOL = I2S_CPOL_LOW; + handle->Init.AudioFreq = I2S_AUDIOFREQ_44K; //Default frequency is 44100Hz. handle->Init.ClockSource = I2S_CLOCK_PLL; - handle->Init.FullDuplexMode = (fdpx == NC) ? I2S_FULLDUPLEXMODE_DISABLE : I2S_FULLDUPLEXMODE_ENABLE; + handle->Init.FullDuplexMode = (fdpx == NC ? I2S_FULLDUPLEXMODE_DISABLE : I2S_FULLDUPLEXMODE_ENABLE); + handle->Init.MCLKOutput = (mclk == NC ? I2S_MCLKOUTPUT_DISABLE : I2S_MCLKOUTPUT_ENABLE); //Davide: Microphones need master clock disabled, while sound terminal needs it enabled. + + DEBUG_PRINTF("--> %s\r\n", __FUNCTION__); + DEBUG_PRINTF(" I2S%u: Mode: %u (%u)\r\n", obj->i2s.module + 1, + (unsigned int)handle->Init.Mode, (unsigned int)mode); + DEBUG_PRINTF(" I2S%u: Standard: %u\r\n", obj->i2s.module + 1, + (unsigned int)handle->Init.Standard); + DEBUG_PRINTF(" I2S%u: DataFormat: %u\r\n", obj->i2s.module + 1, + (unsigned int)handle->Init.DataFormat); + DEBUG_PRINTF(" I2S%u: CPOL: %u\r\n", obj->i2s.module + 1, + (unsigned int)handle->Init.CPOL); + DEBUG_PRINTF(" I2S%u: AudioFreq: %u\r\n", obj->i2s.module + 1, + (unsigned int)handle->Init.AudioFreq); + DEBUG_PRINTF(" I2S%u: ClockSource: %u\r\n", obj->i2s.module + 1, + (unsigned int)handle->Init.ClockSource); + DEBUG_PRINTF(" I2S%u: FullDuplexMode: %u\r\n", obj->i2s.module + 1, + (unsigned int)handle->Init.FullDuplexMode); + DEBUG_PRINTF(" I2S%u: MCLKOutput: %u\r\n", obj->i2s.module + 1, + (unsigned int)handle->Init.MCLKOutput); // Save primary DMA direction obj->dma.dma_direction = dma_direction; - DEBUG_PRINTF("I2S%u: Init\n", obj->i2s.module+1); - 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) - case 0: - __SPI1_FORCE_RESET(); - __SPI1_RELEASE_RESET(); - __SPI1_CLK_DISABLE(); - break; + case 0: + __SPI1_FORCE_RESET(); + __SPI1_RELEASE_RESET(); + __SPI1_CLK_DISABLE(); + break; #endif #if defined(I2S2ext_BASE) - case 1: - __SPI2_FORCE_RESET(); - __SPI2_RELEASE_RESET(); - __SPI2_CLK_DISABLE(); - break; + case 1: + __SPI2_FORCE_RESET(); + __SPI2_RELEASE_RESET(); + __SPI2_CLK_DISABLE(); + break; #endif #if defined(I2S3ext_BASE) - case 2: - __SPI3_FORCE_RESET(); - __SPI3_RELEASE_RESET(); - __SPI3_CLK_DISABLE(); - break; + case 2: + __SPI3_FORCE_RESET(); + __SPI3_RELEASE_RESET(); + __SPI3_CLK_DISABLE(); + break; #endif #if defined(I2S4ext_BASE) - case 3: - __SPI4_FORCE_RESET(); - __SPI4_RELEASE_RESET(); - __SPI4_CLK_DISABLE(); - break; + case 3: + __SPI4_FORCE_RESET(); + __SPI4_RELEASE_RESET(); + __SPI4_CLK_DISABLE(); + break; #endif #if defined(I2S5ext_BASE) - case 4: - __SPI5_FORCE_RESET(); - __SPI5_RELEASE_RESET(); - __SPI5_CLK_DISABLE(); - break; + case 4: + __SPI5_FORCE_RESET(); + __SPI5_RELEASE_RESET(); + __SPI5_CLK_DISABLE(); + break; #endif - default: - MBED_ASSERT(0); - break; + default: + MBED_ASSERT(0); + break; } // betzw - TODO: what about 'PLLI2S'?!? @@ -414,42 +431,48 @@ pin_function(obj->i2s.pin_fdpx, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, 0)); pin_function(obj->i2s.pin_mclk, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, 0)); - DEBUG_PRINTF("I2S%u: Free\n", obj->i2s.module+1); + DEBUG_PRINTF("--> %s\r\n", __FUNCTION__); } -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 - if (fbits == 16) { // format MUST be 16B - handle->Init.DataFormat = I2S_DATAFORMAT_16B; + if (fbits == 16) + { // format MUST be 16B + handle->Init.DataFormat = I2S_DATAFORMAT_16B; } else { // format may NOT be 16B - switch (dbits) { - case 16: - handle->Init.DataFormat = I2S_DATAFORMAT_16B_EXTENDED; - break; - case 24: - handle->Init.DataFormat = I2S_DATAFORMAT_24B; - break; - case 32: - default: - handle->Init.DataFormat = I2S_DATAFORMAT_32B; - break; - } + switch (dbits) + { + case 16: + handle->Init.DataFormat = I2S_DATAFORMAT_16B_EXTENDED; + break; + case 24: + handle->Init.DataFormat = I2S_DATAFORMAT_24B; + break; + case 32: + default: + handle->Init.DataFormat = I2S_DATAFORMAT_32B; + break; + } } handle->Init.CPOL = (polarity == 0) ? I2S_CPOL_LOW : I2S_CPOL_HIGH; - DEBUG_PRINTF("I2S%u: Format: %u (%u, %u), %u (%u)\n", obj->i2s.module+1, - (unsigned int)handle->Init.DataFormat, (unsigned int)dbits, (unsigned int)fbits, - (unsigned int)handle->Init.CPOL, (unsigned int)polarity); + DEBUG_PRINTF("--> %s\r\n", __FUNCTION__); + DEBUG_PRINTF(" I2S%u: DataFormat: %u\r\n", obj->i2s.module + 1, + (unsigned int)handle->Init.DataFormat); + DEBUG_PRINTF(" I2S%u: CPOL: %u\r\n", obj->i2s.module + 1, + (unsigned int)handle->Init.CPOL); + DEBUG_PRINTF(" I2S%u: (dbits, fbits): (%u, %u)\r\n", obj->i2s.module + 1, + (unsigned int)dbits, (unsigned int)fbits); + DEBUG_PRINTF(" I2S%u: Polarity: %u\r\n", obj->i2s.module + 1, + (unsigned int)polarity); 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]; @@ -458,112 +481,160 @@ // Save primary DMA direction obj->dma.dma_direction = dma_direction; - DEBUG_PRINTF("I2S%u: Mode: %u (%u)\n", obj->i2s.module+1, - (unsigned int)handle->Init.Mode, (unsigned int)mode); + DEBUG_PRINTF("--> %s\r\n", __FUNCTION__); + DEBUG_PRINTF(" I2S%u: Mode: %u (%u)\r\n", obj->i2s.module + 1, + (unsigned int)handle->Init.Mode, (unsigned int)mode); + + init_i2s(obj); +} + +void i2s_set_protocol(i2s_t *obj, i2s_bitorder_t protocol) { + I2S_HandleTypeDef *handle = &I2sHandle[obj->i2s.module]; + + switch (protocol) + { + case PHILIPS: + handle->Init.Standard = I2S_STANDARD_PHILIPS; + break; + case MSB: + handle->Init.Standard = I2S_STANDARD_MSB; + break; + case LSB: + handle->Init.Standard = I2S_STANDARD_LSB; + break; + case PCM_SHORT: + handle->Init.Standard = I2S_STANDARD_PCM_SHORT; + break; + case PCM_LONG: + default: + handle->Init.Standard = I2S_STANDARD_PCM_LONG; + break; + } + + DEBUG_PRINTF("--> %s\r\n", __FUNCTION__); + DEBUG_PRINTF(" I2S%u: Standard: %u\r\n", obj->i2s.module + 1, + (unsigned int)handle->Init.Standard); init_i2s(obj); } -void i2s_set_protocol(i2s_t *obj, i2s_bitorder_t protocol) -{ +void i2s_audio_frequency(i2s_t *obj, uint32_t hz) { I2S_HandleTypeDef *handle = &I2sHandle[obj->i2s.module]; - switch (protocol) { - case PHILIPS: - handle->Init.Standard = I2S_STANDARD_PHILIPS; - break; - case MSB: - handle->Init.Standard = I2S_STANDARD_MSB; - break; - case LSB: - handle->Init.Standard = I2S_STANDARD_LSB; - break; - case PCM_SHORT: - handle->Init.Standard = I2S_STANDARD_PCM_SHORT; - break; - case PCM_LONG: - default: - handle->Init.Standard = I2S_STANDARD_PCM_LONG; - break; + if (IS_I2S_AUDIO_FREQ(hz) && (hz != I2S_AUDIOFREQ_DEFAULT)) { + handle->Init.AudioFreq = hz; + } + else if (hz < I2S_AUDIOFREQ_8K) { + handle->Init.AudioFreq = I2S_AUDIOFREQ_8K; + } + else { + handle->Init.AudioFreq = I2S_AUDIOFREQ_192K; } - DEBUG_PRINTF("I2S%u: Protocol: %u (%u)\n", obj->i2s.module+1, - (unsigned int)handle->Init.Standard, (unsigned int)protocol); + /* Configuring PLLI2S. */ + RCC_PeriphCLKInitTypeDef PeriphClkInitStruct; + + /* Getting RTCClockSelection. */ + HAL_RCCEx_GetPeriphCLKConfig(&PeriphClkInitStruct); + + /* Setting configuration. */ + PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_I2S; + + // Davide: All the following values are taken from Table 91 of the + // reference manual for master clock enabled. + switch (hz) { + case I2S_AUDIOFREQ_8K: + PeriphClkInitStruct.PLLI2S.PLLI2SN = 256; + PeriphClkInitStruct.PLLI2S.PLLI2SR = 5; + break; + + case I2S_AUDIOFREQ_16K: + case I2S_AUDIOFREQ_32K: + case (I2S_AUDIOFREQ_32K << 1): + PeriphClkInitStruct.PLLI2S.PLLI2SN = 213; + PeriphClkInitStruct.PLLI2S.PLLI2SR = 2; + break; + + case I2S_AUDIOFREQ_48K: + PeriphClkInitStruct.PLLI2S.PLLI2SN = 258; + PeriphClkInitStruct.PLLI2S.PLLI2SR = 3; + break; + + case I2S_AUDIOFREQ_96K: + PeriphClkInitStruct.PLLI2S.PLLI2SN = 344; + PeriphClkInitStruct.PLLI2S.PLLI2SR = 2; + break; + + case I2S_AUDIOFREQ_44K: + default: + PeriphClkInitStruct.PLLI2S.PLLI2SN = 271; + PeriphClkInitStruct.PLLI2S.PLLI2SR = 2; + break; + } +#ifdef NDEBUG + HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct); +#else + HAL_StatusTypeDef ret = HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct); +#endif + MBED_ASSERT(ret == HAL_OK); + + DEBUG_PRINTF("--> %s\r\n", __FUNCTION__); + DEBUG_PRINTF(" I2S%u: AudioFreq: %u\r\n", obj->i2s.module + 1, + (unsigned int)handle->Init.AudioFreq); init_i2s(obj); } -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)) { - handle->Init.AudioFreq = hz; - } else if (hz < I2S_AUDIOFREQ_8K) { - handle->Init.AudioFreq = I2S_AUDIOFREQ_8K; - } else { - handle->Init.AudioFreq = I2S_AUDIOFREQ_192K; - } - - DEBUG_PRINTF("I2S%u: Audio frequency: %u (%u)\n", obj->i2s.module+1, - (unsigned int)handle->Init.AudioFreq, (unsigned int)hz); - - init_i2s(obj); -} - -uint8_t i2s_get_module(i2s_t *obj) -{ +uint8_t i2s_get_module(i2s_t *obj) { return obj->i2s.module; } -static void i2s_start_asynch_transfer(i2s_t *obj, transfer_type_t transfer_type, - void *tx, void *rx, int length) -{ +static void i2s_start_asynch_transfer(i2s_t *obj, transfer_type_t transfer_type, void *tx, void *rx, int length) { I2S_HandleTypeDef *handle = &I2sHandle[obj->i2s.module]; obj->i2s.transfer_type = transfer_type; // the HAL expects number of transfers instead of number of bytes int words; switch(handle->Init.DataFormat) { - case I2S_DATAFORMAT_16B: - case I2S_DATAFORMAT_16B_EXTENDED: - words = length / 2; - if(words > 0xFFFC) words = 0xFFFC; // truncate in order to respect max DMA length - break; - case I2S_DATAFORMAT_24B: - case I2S_DATAFORMAT_32B: - default: - words = length / 4; - if(words > 0x7FFC) words = 0x7FFC; // truncate in order to respect max DMA length - break; + case I2S_DATAFORMAT_16B: + case I2S_DATAFORMAT_16B_EXTENDED: + words = length / 2; + if(words > 0xFFFC) words = 0xFFFC; // truncate in order to respect max DMA length + break; + case I2S_DATAFORMAT_24B: + case I2S_DATAFORMAT_32B: + default: + words = length / 4; + if(words > 0x7FFC) words = 0x7FFC; // truncate in order to respect max DMA length + break; } // enable the right hal transfer int rc = 0; switch(transfer_type) { - case I2S_TRANSFER_TYPE_TXRX: - // enable the interrupts - NVIC_EnableIRQ(obj->dma.dma[DMA_TX]->dma_stream_irq); - NVIC_EnableIRQ(obj->dma.dma[DMA_RX]->dma_stream_irq); - // trigger DMA transfers - rc = HAL_I2SEx_TransmitReceive_DMA(handle, (uint16_t*)tx, (uint16_t*)rx, (uint16_t)words); - break; - case I2S_TRANSFER_TYPE_TX: - // enable the interrupt - NVIC_EnableIRQ(obj->dma.dma[DMA_TX]->dma_stream_irq); - // trigger DMA transfer - rc = HAL_I2S_Transmit_DMA(handle, (uint16_t*)tx, (uint16_t)words); - break; - case I2S_TRANSFER_TYPE_RX: - // enable the interrupt - NVIC_EnableIRQ(obj->dma.dma[DMA_RX]->dma_stream_irq); - // trigger DMA transfer - rc = HAL_I2S_Receive_DMA(handle, (uint16_t*)rx, (uint16_t)words); - break; + case I2S_TRANSFER_TYPE_TXRX: + // enable the interrupts + NVIC_EnableIRQ(obj->dma.dma[DMA_TX]->dma_stream_irq); + NVIC_EnableIRQ(obj->dma.dma[DMA_RX]->dma_stream_irq); + // trigger DMA transfers + rc = HAL_I2SEx_TransmitReceive_DMA(handle, (uint16_t*)tx, (uint16_t*)rx, (uint16_t)words); + break; + case I2S_TRANSFER_TYPE_TX: + // enable the interrupt + NVIC_EnableIRQ(obj->dma.dma[DMA_TX]->dma_stream_irq); + // trigger DMA transfer + rc = HAL_I2S_Transmit_DMA(handle, (uint16_t*)tx, (uint16_t)words); + break; + case I2S_TRANSFER_TYPE_RX: + // enable the interrupt + NVIC_EnableIRQ(obj->dma.dma[DMA_RX]->dma_stream_irq); + // trigger DMA transfer + rc = HAL_I2S_Receive_DMA(handle, (uint16_t*)rx, (uint16_t)words); + break; } if (rc) { - DEBUG_PRINTF("I2S%u: RC=%d\n", obj->i2s.module+1, rc); + DEBUG_PRINTF(" I2S%u: RC: %d\r\n", obj->i2s.module + 1, rc); } return; @@ -574,8 +645,7 @@ void *tx, int tx_length, void *rx, int rx_length, bool circular, i2s_dma_prio_t prio, - uint32_t handler_tx, uint32_t handler_rx, uint32_t event) -{ + uint32_t handler_tx, uint32_t handler_rx, uint32_t event) { // check which use-case we have bool use_tx = (tx != NULL && tx_length > 0); bool use_rx = (rx != NULL && rx_length > 0); @@ -600,29 +670,28 @@ obj->i2s.event = event; - DEBUG_PRINTF("I2S%u: Transfer: %u, %u\n", obj->i2s.module+1, tx_length, rx_length); + DEBUG_PRINTF(" I2S%u: Transfer: %u, %u\r\n", obj->i2s.module + 1, tx_length, rx_length); // register the thunking handler - if(use_tx) { - NVIC_SetVector(obj->dma.dma[DMA_TX]->dma_stream_irq, handler_tx); + if (use_tx) { + NVIC_SetVector(obj->dma.dma[DMA_TX]->dma_stream_irq, handler_tx); } - if(use_rx) { - NVIC_SetVector(obj->dma.dma[DMA_RX]->dma_stream_irq, handler_rx); + if (use_rx) { + NVIC_SetVector(obj->dma.dma[DMA_RX]->dma_stream_irq, handler_rx); } // enable the right hal transfer if (use_tx && use_rx) { - int size = (tx_length < rx_length)? tx_length : rx_length; - i2s_start_asynch_transfer(obj, I2S_TRANSFER_TYPE_TXRX, tx, rx, size); + int size = (tx_length < rx_length)? tx_length : rx_length; + i2s_start_asynch_transfer(obj, I2S_TRANSFER_TYPE_TXRX, tx, rx, size); } else if (use_tx) { - i2s_start_asynch_transfer(obj, I2S_TRANSFER_TYPE_TX, tx, NULL, tx_length); + i2s_start_asynch_transfer(obj, I2S_TRANSFER_TYPE_TX, tx, NULL, tx_length); } else if (use_rx) { - i2s_start_asynch_transfer(obj, I2S_TRANSFER_TYPE_RX, NULL, rx, rx_length); + i2s_start_asynch_transfer(obj, I2S_TRANSFER_TYPE_RX, NULL, rx, rx_length); } } -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 @@ -636,150 +705,153 @@ // call the Cube handler, this will update the handle HAL_DMA_IRQHandler(dma_handle); - switch(HAL_I2S_GetState(i2s_handle)) { - case HAL_I2S_STATE_READY: { - // adjust buffer positions (betzw - TODO: to be checked for DMA transfers!!!) - int tx_size = (i2s_handle->TxXferSize - i2s_handle->TxXferCount); - int rx_size = (i2s_handle->RxXferSize - i2s_handle->RxXferCount); + switch(HAL_I2S_GetState(i2s_handle)) + { + case HAL_I2S_STATE_READY: { + // adjust buffer positions (betzw - TODO: to be checked for DMA transfers!!!) + int tx_size = (i2s_handle->TxXferSize - i2s_handle->TxXferCount); + int rx_size = (i2s_handle->RxXferSize - i2s_handle->RxXferCount); - // take data format into consideration - switch(i2s_handle->Init.DataFormat) { - case I2S_DATAFORMAT_16B: - case I2S_DATAFORMAT_16B_EXTENDED: - tx_size *= 2; - rx_size *= 2; - break; - case I2S_DATAFORMAT_24B: - case I2S_DATAFORMAT_32B: - default: - tx_size *= 4; - rx_size *= 4; - break; - } + // take data format into consideration + switch(i2s_handle->Init.DataFormat) + { + case I2S_DATAFORMAT_16B: + case I2S_DATAFORMAT_16B_EXTENDED: + tx_size *= 2; + rx_size *= 2; + break; + case I2S_DATAFORMAT_24B: + case I2S_DATAFORMAT_32B: + default: + tx_size *= 4; + rx_size *= 4; + break; + } - // adjust buffer positions - if (obj->i2s.transfer_type != I2S_TRANSFER_TYPE_RX) { - obj->tx_buff.pos += tx_size; - } - if (obj->i2s.transfer_type != I2S_TRANSFER_TYPE_TX) { - obj->rx_buff.pos += rx_size; - } + // adjust buffer positions + if (obj->i2s.transfer_type != I2S_TRANSFER_TYPE_RX) { + obj->tx_buff.pos += tx_size; + } + if (obj->i2s.transfer_type != I2S_TRANSFER_TYPE_TX) { + obj->rx_buff.pos += rx_size; + } - if (i2s_handle->TxXferCount > 0) { - DEBUG_PRINTF("I2S%u: TxXferCount: %u\n", obj->i2s.module+1, i2s_handle->TxXferCount); - } - if (i2s_handle->RxXferCount > 0) { - DEBUG_PRINTF("I2S%u: RxXferCount: %u\n", obj->i2s.module+1, i2s_handle->RxXferCount); - } - } - /* no break */ + if (i2s_handle->TxXferCount > 0) { + DEBUG_PRINTF(" I2S%u: TxXferCount: %u\r\n", obj->i2s.module + 1, i2s_handle->TxXferCount); + } + if (i2s_handle->RxXferCount > 0) { + DEBUG_PRINTF(" I2S%u: RxXferCount: %u\r\n", obj->i2s.module + 1, i2s_handle->RxXferCount); + } + } + /* no break */ - case HAL_I2S_STATE_BUSY_TX: - case HAL_I2S_STATE_BUSY_RX: - case HAL_I2S_STATE_BUSY_TX_RX: { - int error = HAL_I2S_GetError(i2s_handle); + case HAL_I2S_STATE_BUSY_TX: + case HAL_I2S_STATE_BUSY_RX: + case HAL_I2S_STATE_BUSY_TX_RX: + { + int error = HAL_I2S_GetError(i2s_handle); - if(error != HAL_I2S_ERROR_NONE) { - // something went wrong and the transfer has definitely completed - event = ((direction == DMA_TX) ? I2S_EVENT_TX_ERROR : I2S_EVENT_RX_ERROR) | I2S_EVENT_INTERNAL_TRANSFER_COMPLETE; + if (error != HAL_I2S_ERROR_NONE) { + // something went wrong and the transfer has definitely completed + event = ((direction == DMA_TX) ? I2S_EVENT_TX_ERROR : I2S_EVENT_RX_ERROR) | I2S_EVENT_INTERNAL_TRANSFER_COMPLETE; - if (error & HAL_I2S_ERROR_OVR) { - // buffer overrun - event |= I2S_EVENT_RX_OVERFLOW; - } + if (error & HAL_I2S_ERROR_OVR) { + // buffer overrun + event |= I2S_EVENT_RX_OVERFLOW; + } - if (error & HAL_I2S_ERROR_UDR) { - // buffer underrun - event |= I2S_EVENT_TX_UNDERRUN; - } + if (error & HAL_I2S_ERROR_UDR) { + // buffer underrun + event |= I2S_EVENT_TX_UNDERRUN; + } - // cleanup DMA (after error) - dma_i2s_free(obj, direction); - } else { // no error detected - HAL_DMA_StateTypeDef dma_state = HAL_DMA_GetState(dma_handle); + // cleanup DMA (after error) + dma_i2s_free(obj, direction); + } else + { // no error detected + HAL_DMA_StateTypeDef dma_state = HAL_DMA_GetState(dma_handle); - switch(dma_state) { - case HAL_DMA_STATE_READY_HALF_MEM0: - case HAL_DMA_STATE_READY_HALF_MEM1: - event = ((direction == DMA_TX) ? I2S_EVENT_TX_HALF_COMPLETE : I2S_EVENT_RX_HALF_COMPLETE); - break; - case HAL_DMA_STATE_READY_MEM0: - case HAL_DMA_STATE_READY_MEM1: - event = ((direction == DMA_TX) ? I2S_EVENT_TX_COMPLETE : I2S_EVENT_RX_COMPLETE); - - if(dma_handle->Init.Mode != DMA_CIRCULAR) { - if (!i2s_active(obj)) { // Check for full-duplex transfer complete! - event |= I2S_EVENT_INTERNAL_TRANSFER_COMPLETE; - } + switch(dma_state) + { + case HAL_DMA_STATE_READY_HALF_MEM0: + case HAL_DMA_STATE_READY_HALF_MEM1: + event = ((direction == DMA_TX) ? I2S_EVENT_TX_HALF_COMPLETE : I2S_EVENT_RX_HALF_COMPLETE); + break; + case HAL_DMA_STATE_READY_MEM0: + case HAL_DMA_STATE_READY_MEM1: + event = ((direction == DMA_TX) ? I2S_EVENT_TX_COMPLETE : I2S_EVENT_RX_COMPLETE); + if(dma_handle->Init.Mode != DMA_CIRCULAR) + { + if (!i2s_active(obj)) + { // Check for full-duplex transfer complete! + event |= I2S_EVENT_INTERNAL_TRANSFER_COMPLETE; + } - // cleanup DMA (because we are done) - dma_i2s_free(obj, direction); - } - break; + // cleanup DMA (because we are done) + dma_i2s_free(obj, direction); + } + break; + default: + printf("betzw(%s, %d): dma_state=0x%x\r\n", __func__, __LINE__, (int)dma_state); + MBED_ASSERT(0); + break; + } + } + } + break; default: - printf("betzw(%s, %d): dma_state=0x%x\r\n", __func__, __LINE__, (int)dma_state); - MBED_ASSERT(0); - break; - } - } - } - break; - - default: - // nothing to do?!? - break; + // nothing to do?!? + break; } - if (event) DEBUG_PRINTF("I2S%u: Event: 0x%x\n", obj->i2s.module+1, event); + if (event) DEBUG_PRINTF(" I2S%u: Event: 0x%x\r\n", obj->i2s.module + 1, event); 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); - switch(state) { - case HAL_I2S_STATE_RESET: - case HAL_I2S_STATE_READY: - case HAL_I2S_STATE_ERROR: - return 0; - default: - return -1; + switch(state){ + case HAL_I2S_STATE_RESET: + case HAL_I2S_STATE_READY: + case HAL_I2S_STATE_ERROR: + return 0; + default: + return -1; } } -void i2s_abort_asynch(i2s_t *obj) -{ +void i2s_abort_asynch(i2s_t *obj) { I2S_HandleTypeDef *i2s_handle = &I2sHandle[obj->i2s.module]; // Stop transfer HAL_I2S_DMAStop(i2s_handle); if(obj->dma.dma[DMA_TX] != NULL) { - DMA_HandleTypeDef *dma_handle_tx = &DMaHandles[obj->i2s.module][DMA_TX]; + DMA_HandleTypeDef *dma_handle_tx = &DMaHandles[obj->i2s.module][DMA_TX]; - // disable interrupt & free resource - dma_i2s_free(obj, DMA_TX); - - //clean up - __HAL_DMA_DISABLE(dma_handle_tx); - HAL_DMA_DeInit(dma_handle_tx); - HAL_DMA_Init(dma_handle_tx); - __HAL_DMA_ENABLE(dma_handle_tx); + // disable interrupt & free resource + dma_i2s_free(obj, DMA_TX); + + //clean up + __HAL_DMA_DISABLE(dma_handle_tx); + HAL_DMA_DeInit(dma_handle_tx); + HAL_DMA_Init(dma_handle_tx); + __HAL_DMA_ENABLE(dma_handle_tx); } if(obj->dma.dma[DMA_RX] != NULL) { - DMA_HandleTypeDef *dma_handle_rx = &DMaHandles[obj->i2s.module][DMA_RX]; + DMA_HandleTypeDef *dma_handle_rx = &DMaHandles[obj->i2s.module][DMA_RX]; - // disable interrupt & free resource - dma_i2s_free(obj, DMA_RX); + // disable interrupt & free resource + dma_i2s_free(obj, DMA_RX); - //clean up - __HAL_DMA_DISABLE(dma_handle_rx); - HAL_DMA_DeInit(dma_handle_rx); - HAL_DMA_Init(dma_handle_rx); - __HAL_DMA_ENABLE(dma_handle_rx); + //clean up + __HAL_DMA_DISABLE(dma_handle_rx); + HAL_DMA_DeInit(dma_handle_rx); + HAL_DMA_Init(dma_handle_rx); + __HAL_DMA_ENABLE(dma_handle_rx); } // clean-up I2S