Il y avait des problèmes dans la libraire...

Dependents:   X_NUCLEO_CCA02M1

Fork of ST_I2S by ST

Committer:
Wolfgang Betz
Date:
Tue Nov 29 14:43:26 2016 +0100
Revision:
1:f90318e0923b
Child:
5:74da3773bf43
Child:
2:0c9ce59aee25
Rename & adjust

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Wolfgang Betz 1:f90318e0923b 1 #include "mbed_assert.h"
Wolfgang Betz 1:f90318e0923b 2 #include "mbed_error.h"
Wolfgang Betz 1:f90318e0923b 3 #include "stm_i2s_api.h"
Wolfgang Betz 1:f90318e0923b 4
Wolfgang Betz 1:f90318e0923b 5 #include "stm_dma_caps.h"
Wolfgang Betz 1:f90318e0923b 6
Wolfgang Betz 1:f90318e0923b 7 #if DEVICE_I2S
Wolfgang Betz 1:f90318e0923b 8
Wolfgang Betz 1:f90318e0923b 9 #include <math.h>
Wolfgang Betz 1:f90318e0923b 10 #include <string.h>
Wolfgang Betz 1:f90318e0923b 11 #include "cmsis.h"
Wolfgang Betz 1:f90318e0923b 12 #include "pinmap.h"
Wolfgang Betz 1:f90318e0923b 13 #include "PeripheralPins.h"
Wolfgang Betz 1:f90318e0923b 14
Wolfgang Betz 1:f90318e0923b 15 // #define DEBUG_STDIO 1 // betzw - TODO: temporarily enable debug printfs
Wolfgang Betz 1:f90318e0923b 16
Wolfgang Betz 1:f90318e0923b 17 #ifndef DEBUG_STDIO
Wolfgang Betz 1:f90318e0923b 18 # define DEBUG_STDIO 0
Wolfgang Betz 1:f90318e0923b 19 #endif
Wolfgang Betz 1:f90318e0923b 20
Wolfgang Betz 1:f90318e0923b 21 #if DEBUG_STDIO
Wolfgang Betz 1:f90318e0923b 22 # include <stdio.h>
Wolfgang Betz 1:f90318e0923b 23 # define DEBUG_PRINTF(...) do { printf(__VA_ARGS__); } while(0)
Wolfgang Betz 1:f90318e0923b 24 #else
Wolfgang Betz 1:f90318e0923b 25 # define DEBUG_PRINTF(...) {}
Wolfgang Betz 1:f90318e0923b 26 #endif
Wolfgang Betz 1:f90318e0923b 27
Wolfgang Betz 1:f90318e0923b 28 typedef enum {
Wolfgang Betz 1:f90318e0923b 29 I2S_TRANSFER_TYPE_TX = 1,
Wolfgang Betz 1:f90318e0923b 30 I2S_TRANSFER_TYPE_RX = 2,
Wolfgang Betz 1:f90318e0923b 31 I2S_TRANSFER_TYPE_TXRX = 3,
Wolfgang Betz 1:f90318e0923b 32 } transfer_type_t;
Wolfgang Betz 1:f90318e0923b 33
Wolfgang Betz 1:f90318e0923b 34 typedef struct {
Wolfgang Betz 1:f90318e0923b 35 DMA_HandleTypeDef tx_dma_handle;
Wolfgang Betz 1:f90318e0923b 36 DMA_HandleTypeDef rx_dma_handle;
Wolfgang Betz 1:f90318e0923b 37 } dma_handles_t;
Wolfgang Betz 1:f90318e0923b 38
Wolfgang Betz 1:f90318e0923b 39 #define I2S_NUM (5) // betzw: this approach wastes quite a bit of memory - TO BE IMPROVED!?!?
Wolfgang Betz 1:f90318e0923b 40
Wolfgang Betz 1:f90318e0923b 41 static I2S_HandleTypeDef I2sHandle[I2S_NUM];
Wolfgang Betz 1:f90318e0923b 42 static DMA_HandleTypeDef DMaHandles[I2S_NUM][NUM_OF_DIRECTIONS];
Wolfgang Betz 1:f90318e0923b 43
Wolfgang Betz 1:f90318e0923b 44 static void init_i2s(i2s_t *obj)
Wolfgang Betz 1:f90318e0923b 45 {
Wolfgang Betz 1:f90318e0923b 46 I2S_HandleTypeDef *handle = &I2sHandle[obj->i2s.module];
Wolfgang Betz 1:f90318e0923b 47
Wolfgang Betz 1:f90318e0923b 48 __HAL_I2S_DISABLE(handle);
Wolfgang Betz 1:f90318e0923b 49 HAL_I2S_Init(handle);
Wolfgang Betz 1:f90318e0923b 50 __HAL_I2S_ENABLE(handle);
Wolfgang Betz 1:f90318e0923b 51 }
Wolfgang Betz 1:f90318e0923b 52
Wolfgang Betz 1:f90318e0923b 53 static void init_dmas(i2s_t *obj)
Wolfgang Betz 1:f90318e0923b 54 {
Wolfgang Betz 1:f90318e0923b 55 DMA_HandleTypeDef *primary_handle = NULL;
Wolfgang Betz 1:f90318e0923b 56 DMA_HandleTypeDef *secondary_handle = NULL;
Wolfgang Betz 1:f90318e0923b 57 DMA_HandleTypeDef *hdmatx = NULL;
Wolfgang Betz 1:f90318e0923b 58
Wolfgang Betz 1:f90318e0923b 59 switch(obj->dma.dma_direction) {
Wolfgang Betz 1:f90318e0923b 60 case DMA_TX:
Wolfgang Betz 1:f90318e0923b 61 if(obj->dma.dma[DMA_TX] != NULL) {
Wolfgang Betz 1:f90318e0923b 62 hdmatx = primary_handle = &DMaHandles[obj->i2s.module][DMA_TX];
Wolfgang Betz 1:f90318e0923b 63 }
Wolfgang Betz 1:f90318e0923b 64 if(obj->dma.dma[DMA_RX] != NULL) {
Wolfgang Betz 1:f90318e0923b 65 secondary_handle = &DMaHandles[obj->i2s.module][DMA_RX];
Wolfgang Betz 1:f90318e0923b 66 }
Wolfgang Betz 1:f90318e0923b 67 break;
Wolfgang Betz 1:f90318e0923b 68 case DMA_RX:
Wolfgang Betz 1:f90318e0923b 69 default:
Wolfgang Betz 1:f90318e0923b 70 if(obj->dma.dma[DMA_RX] != NULL) {
Wolfgang Betz 1:f90318e0923b 71 primary_handle = &DMaHandles[obj->i2s.module][DMA_RX];
Wolfgang Betz 1:f90318e0923b 72 }
Wolfgang Betz 1:f90318e0923b 73 if(obj->dma.dma[DMA_TX] != NULL) {
Wolfgang Betz 1:f90318e0923b 74 hdmatx = secondary_handle = &DMaHandles[obj->i2s.module][DMA_TX];
Wolfgang Betz 1:f90318e0923b 75 }
Wolfgang Betz 1:f90318e0923b 76 break;
Wolfgang Betz 1:f90318e0923b 77 }
Wolfgang Betz 1:f90318e0923b 78
Wolfgang Betz 1:f90318e0923b 79 if(primary_handle != NULL) {
Wolfgang Betz 1:f90318e0923b 80 __HAL_DMA_DISABLE(primary_handle);
Wolfgang Betz 1:f90318e0923b 81 HAL_DMA_Init(primary_handle);
Wolfgang Betz 1:f90318e0923b 82
Wolfgang Betz 1:f90318e0923b 83 if(hdmatx == primary_handle) {
Wolfgang Betz 1:f90318e0923b 84 __HAL_LINKDMA(&I2sHandle[obj->i2s.module], hdmatx, *primary_handle);
Wolfgang Betz 1:f90318e0923b 85 } else {
Wolfgang Betz 1:f90318e0923b 86 __HAL_LINKDMA(&I2sHandle[obj->i2s.module], hdmarx, *primary_handle);
Wolfgang Betz 1:f90318e0923b 87 }
Wolfgang Betz 1:f90318e0923b 88 }
Wolfgang Betz 1:f90318e0923b 89
Wolfgang Betz 1:f90318e0923b 90 if(secondary_handle != NULL) {
Wolfgang Betz 1:f90318e0923b 91 __HAL_DMA_DISABLE(secondary_handle);
Wolfgang Betz 1:f90318e0923b 92 HAL_DMA_Init(secondary_handle);
Wolfgang Betz 1:f90318e0923b 93
Wolfgang Betz 1:f90318e0923b 94 if(hdmatx == secondary_handle) {
Wolfgang Betz 1:f90318e0923b 95 __HAL_LINKDMA(&I2sHandle[obj->i2s.module], hdmatx, *secondary_handle);
Wolfgang Betz 1:f90318e0923b 96 } else {
Wolfgang Betz 1:f90318e0923b 97 __HAL_LINKDMA(&I2sHandle[obj->i2s.module], hdmarx, *secondary_handle);
Wolfgang Betz 1:f90318e0923b 98 }
Wolfgang Betz 1:f90318e0923b 99 }
Wolfgang Betz 1:f90318e0923b 100 }
Wolfgang Betz 1:f90318e0923b 101
Wolfgang Betz 1:f90318e0923b 102 static inline uint32_t i2s_get_mode(i2s_mode_t mode, uint8_t *direction) {
Wolfgang Betz 1:f90318e0923b 103 switch(mode) {
Wolfgang Betz 1:f90318e0923b 104 case SLAVE_TX:
Wolfgang Betz 1:f90318e0923b 105 *direction = DMA_TX;
Wolfgang Betz 1:f90318e0923b 106 return I2S_MODE_SLAVE_TX;
Wolfgang Betz 1:f90318e0923b 107 case SLAVE_RX:
Wolfgang Betz 1:f90318e0923b 108 *direction = DMA_RX;
Wolfgang Betz 1:f90318e0923b 109 return I2S_MODE_SLAVE_RX;
Wolfgang Betz 1:f90318e0923b 110 case MASTER_TX:
Wolfgang Betz 1:f90318e0923b 111 *direction = DMA_TX;
Wolfgang Betz 1:f90318e0923b 112 return I2S_MODE_MASTER_TX;
Wolfgang Betz 1:f90318e0923b 113 case MASTER_RX:
Wolfgang Betz 1:f90318e0923b 114 default:
Wolfgang Betz 1:f90318e0923b 115 *direction = DMA_RX;
Wolfgang Betz 1:f90318e0923b 116 return I2S_MODE_MASTER_RX;
Wolfgang Betz 1:f90318e0923b 117 }
Wolfgang Betz 1:f90318e0923b 118 }
Wolfgang Betz 1:f90318e0923b 119
Wolfgang Betz 1:f90318e0923b 120 static inline uint32_t i2s_get_priority(i2s_dma_prio_t priority) {
Wolfgang Betz 1:f90318e0923b 121 switch(priority) {
Wolfgang Betz 1:f90318e0923b 122 case LOW:
Wolfgang Betz 1:f90318e0923b 123 return DMA_PRIORITY_LOW;
Wolfgang Betz 1:f90318e0923b 124 case URGENT:
Wolfgang Betz 1:f90318e0923b 125 return DMA_PRIORITY_VERY_HIGH;
Wolfgang Betz 1:f90318e0923b 126 case HIGH:
Wolfgang Betz 1:f90318e0923b 127 return DMA_PRIORITY_HIGH;
Wolfgang Betz 1:f90318e0923b 128 default:
Wolfgang Betz 1:f90318e0923b 129 return DMA_PRIORITY_MEDIUM;
Wolfgang Betz 1:f90318e0923b 130 }
Wolfgang Betz 1:f90318e0923b 131 }
Wolfgang Betz 1:f90318e0923b 132
Wolfgang Betz 1:f90318e0923b 133 static void dma_i2s_init(i2s_t *obj, bool *use_tx, bool *use_rx, bool circular, i2s_dma_prio_t prio) {
Wolfgang Betz 1:f90318e0923b 134 // DMA declarations
Wolfgang Betz 1:f90318e0923b 135 DMA_HandleTypeDef *primary_handle = &DMaHandles[obj->i2s.module][obj->dma.dma_direction];
Wolfgang Betz 1:f90318e0923b 136 DMA_HandleTypeDef *secondary_handle = NULL;
Wolfgang Betz 1:f90318e0923b 137
Wolfgang Betz 1:f90318e0923b 138 // DMA initialization & configuration
Wolfgang Betz 1:f90318e0923b 139 dma_init();
Wolfgang Betz 1:f90318e0923b 140 obj->dma.dma[DMA_TX] = obj->dma.dma[DMA_RX] = NULL;
Wolfgang Betz 1:f90318e0923b 141
Wolfgang Betz 1:f90318e0923b 142 switch(obj->dma.dma_direction) {
Wolfgang Betz 1:f90318e0923b 143 case DMA_TX:
Wolfgang Betz 1:f90318e0923b 144 if(*use_tx) {
Wolfgang Betz 1:f90318e0923b 145 obj->dma.dma[DMA_TX] = dma_channel_allocate(MAKE_CAP(obj->dma.dma_device, DMA_TX));
Wolfgang Betz 1:f90318e0923b 146 MBED_ASSERT(obj->dma.dma[DMA_TX] != DMA_ERROR_OUT_OF_CHANNELS);
Wolfgang Betz 1:f90318e0923b 147 }
Wolfgang Betz 1:f90318e0923b 148 break;
Wolfgang Betz 1:f90318e0923b 149 case DMA_RX:
Wolfgang Betz 1:f90318e0923b 150 default:
Wolfgang Betz 1:f90318e0923b 151 if(*use_rx) {
Wolfgang Betz 1:f90318e0923b 152 obj->dma.dma[DMA_RX] = dma_channel_allocate(MAKE_CAP(obj->dma.dma_device, DMA_RX));
Wolfgang Betz 1:f90318e0923b 153 MBED_ASSERT(obj->dma.dma[DMA_RX] != DMA_ERROR_OUT_OF_CHANNELS);
Wolfgang Betz 1:f90318e0923b 154 }
Wolfgang Betz 1:f90318e0923b 155 break;
Wolfgang Betz 1:f90318e0923b 156 }
Wolfgang Betz 1:f90318e0923b 157
Wolfgang Betz 1:f90318e0923b 158 // Primary DMA configuration
Wolfgang Betz 1:f90318e0923b 159 if(obj->dma.dma[obj->dma.dma_direction] != NULL) {
Wolfgang Betz 1:f90318e0923b 160 primary_handle->Instance = obj->dma.dma[obj->dma.dma_direction]->dma_stream;
Wolfgang Betz 1:f90318e0923b 161 primary_handle->Init.Channel = obj->dma.dma[obj->dma.dma_direction]->channel_nr;
Wolfgang Betz 1:f90318e0923b 162 primary_handle->Init.Direction = (obj->dma.dma_direction == DMA_TX) ?
Wolfgang Betz 1:f90318e0923b 163 DMA_MEMORY_TO_PERIPH : DMA_PERIPH_TO_MEMORY;
Wolfgang Betz 1:f90318e0923b 164 primary_handle->Init.FIFOMode = DMA_FIFOMODE_DISABLE;
Wolfgang Betz 1:f90318e0923b 165 primary_handle->Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
Wolfgang Betz 1:f90318e0923b 166 primary_handle->Init.MemBurst = DMA_MBURST_SINGLE;
Wolfgang Betz 1:f90318e0923b 167 primary_handle->Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
Wolfgang Betz 1:f90318e0923b 168 primary_handle->Init.MemInc = DMA_MINC_ENABLE;
Wolfgang Betz 1:f90318e0923b 169 primary_handle->Init.Mode = (circular ? DMA_CIRCULAR : DMA_NORMAL);
Wolfgang Betz 1:f90318e0923b 170 primary_handle->Init.PeriphBurst = DMA_PBURST_SINGLE;
Wolfgang Betz 1:f90318e0923b 171 primary_handle->Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
Wolfgang Betz 1:f90318e0923b 172 primary_handle->Init.PeriphInc = DMA_PINC_DISABLE;
Wolfgang Betz 1:f90318e0923b 173 primary_handle->Init.Priority = i2s_get_priority(prio);
Wolfgang Betz 1:f90318e0923b 174 }
Wolfgang Betz 1:f90318e0923b 175
Wolfgang Betz 1:f90318e0923b 176 // Allocate secondary DMA channel (if full-duplex)
Wolfgang Betz 1:f90318e0923b 177 if(obj->i2s.pin_fdpx != NC) {
Wolfgang Betz 1:f90318e0923b 178 switch(obj->dma.dma_direction) {
Wolfgang Betz 1:f90318e0923b 179 case DMA_TX:
Wolfgang Betz 1:f90318e0923b 180 if(*use_rx) {
Wolfgang Betz 1:f90318e0923b 181 obj->dma.dma[DMA_RX] = dma_channel_allocate(MAKE_CAP(obj->dma.dma_device, DMA_RX));
Wolfgang Betz 1:f90318e0923b 182 secondary_handle = &DMaHandles[obj->i2s.module][DMA_RX];
Wolfgang Betz 1:f90318e0923b 183 MBED_ASSERT(obj->dma.dma[DMA_RX] != DMA_ERROR_OUT_OF_CHANNELS);
Wolfgang Betz 1:f90318e0923b 184 }
Wolfgang Betz 1:f90318e0923b 185 break;
Wolfgang Betz 1:f90318e0923b 186 case DMA_RX:
Wolfgang Betz 1:f90318e0923b 187 default:
Wolfgang Betz 1:f90318e0923b 188 if(*use_tx) {
Wolfgang Betz 1:f90318e0923b 189 obj->dma.dma[DMA_TX] = dma_channel_allocate(MAKE_CAP(obj->dma.dma_device, DMA_TX));
Wolfgang Betz 1:f90318e0923b 190 secondary_handle = &DMaHandles[obj->i2s.module][DMA_TX];
Wolfgang Betz 1:f90318e0923b 191 MBED_ASSERT(obj->dma.dma[DMA_TX] != DMA_ERROR_OUT_OF_CHANNELS);
Wolfgang Betz 1:f90318e0923b 192 }
Wolfgang Betz 1:f90318e0923b 193 break;
Wolfgang Betz 1:f90318e0923b 194 }
Wolfgang Betz 1:f90318e0923b 195 }
Wolfgang Betz 1:f90318e0923b 196
Wolfgang Betz 1:f90318e0923b 197 // Secondary DMA configuration
Wolfgang Betz 1:f90318e0923b 198 if(secondary_handle != NULL) {
Wolfgang Betz 1:f90318e0923b 199 uint8_t secondary_dma_direction = (obj->dma.dma_direction == DMA_TX) ? DMA_RX : DMA_TX;
Wolfgang Betz 1:f90318e0923b 200
Wolfgang Betz 1:f90318e0923b 201 secondary_handle->Instance = obj->dma.dma[secondary_dma_direction]->dma_stream;
Wolfgang Betz 1:f90318e0923b 202 secondary_handle->Init.Channel = obj->dma.dma[secondary_dma_direction]->channel_nr_fd;
Wolfgang Betz 1:f90318e0923b 203 secondary_handle->Init.Direction = (secondary_dma_direction == DMA_TX) ?
Wolfgang Betz 1:f90318e0923b 204 DMA_MEMORY_TO_PERIPH : DMA_PERIPH_TO_MEMORY;
Wolfgang Betz 1:f90318e0923b 205 secondary_handle->Init.FIFOMode = DMA_FIFOMODE_DISABLE;
Wolfgang Betz 1:f90318e0923b 206 secondary_handle->Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
Wolfgang Betz 1:f90318e0923b 207 secondary_handle->Init.MemBurst = DMA_MBURST_SINGLE;
Wolfgang Betz 1:f90318e0923b 208 secondary_handle->Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
Wolfgang Betz 1:f90318e0923b 209 secondary_handle->Init.MemInc = DMA_MINC_ENABLE;
Wolfgang Betz 1:f90318e0923b 210 secondary_handle->Init.Mode = (circular ? DMA_CIRCULAR : DMA_NORMAL);
Wolfgang Betz 1:f90318e0923b 211 secondary_handle->Init.PeriphBurst = DMA_PBURST_SINGLE;
Wolfgang Betz 1:f90318e0923b 212 secondary_handle->Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
Wolfgang Betz 1:f90318e0923b 213 secondary_handle->Init.PeriphInc = DMA_PINC_DISABLE;
Wolfgang Betz 1:f90318e0923b 214 secondary_handle->Init.Priority = i2s_get_priority(prio);
Wolfgang Betz 1:f90318e0923b 215 }
Wolfgang Betz 1:f90318e0923b 216
Wolfgang Betz 1:f90318e0923b 217 if(obj->dma.dma[DMA_TX] == NULL) *use_tx = false;
Wolfgang Betz 1:f90318e0923b 218 if(obj->dma.dma[DMA_RX] == NULL) *use_rx = false;
Wolfgang Betz 1:f90318e0923b 219
Wolfgang Betz 1:f90318e0923b 220 // don't do anything, if the buffers aren't valid
Wolfgang Betz 1:f90318e0923b 221 if (!use_tx && !use_rx) {
Wolfgang Betz 1:f90318e0923b 222 DEBUG_PRINTF("I2S%u: No DMAs to init\n", obj->i2s.module+1);
Wolfgang Betz 1:f90318e0923b 223 return;
Wolfgang Betz 1:f90318e0923b 224 }
Wolfgang Betz 1:f90318e0923b 225
Wolfgang Betz 1:f90318e0923b 226 DEBUG_PRINTF("I2S%u: DMA(s) Init\n", obj->i2s.module+1);
Wolfgang Betz 1:f90318e0923b 227 init_dmas(obj);
Wolfgang Betz 1:f90318e0923b 228 }
Wolfgang Betz 1:f90318e0923b 229
Wolfgang Betz 1:f90318e0923b 230 static void dma_i2s_free(i2s_t *obj, uint8_t direction) {
Wolfgang Betz 1:f90318e0923b 231 const struct dma_stream_s *stream = obj->dma.dma[direction];
Wolfgang Betz 1:f90318e0923b 232
Wolfgang Betz 1:f90318e0923b 233 MBED_ASSERT(stream != NULL);
Wolfgang Betz 1:f90318e0923b 234
Wolfgang Betz 1:f90318e0923b 235 // disable irq
Wolfgang Betz 1:f90318e0923b 236 NVIC_DisableIRQ(stream->dma_stream_irq);
Wolfgang Betz 1:f90318e0923b 237
Wolfgang Betz 1:f90318e0923b 238 // free channel
Wolfgang Betz 1:f90318e0923b 239 dma_channel_free((void*)stream);
Wolfgang Betz 1:f90318e0923b 240 obj->dma.dma[direction] = NULL;
Wolfgang Betz 1:f90318e0923b 241 }
Wolfgang Betz 1:f90318e0923b 242
Wolfgang Betz 1:f90318e0923b 243 void i2s_init(i2s_t *obj, PinName data, PinName sclk, PinName wsel, PinName fdpx, PinName mclk, i2s_mode_t mode)
Wolfgang Betz 1:f90318e0923b 244 {
Wolfgang Betz 1:f90318e0923b 245 uint8_t dma_dev = 0, dma_direction = 0;
Wolfgang Betz 1:f90318e0923b 246
Wolfgang Betz 1:f90318e0923b 247 // Determine the I2S/SPI to use
Wolfgang Betz 1:f90318e0923b 248 SPIName i2s_data = (SPIName)pinmap_peripheral(data, PinMap_I2S_DATA);
Wolfgang Betz 1:f90318e0923b 249 SPIName i2s_sclk = (SPIName)pinmap_peripheral(sclk, PinMap_I2S_SCLK);
Wolfgang Betz 1:f90318e0923b 250
Wolfgang Betz 1:f90318e0923b 251 SPIName i2s_wsel = (SPIName)pinmap_peripheral(wsel, PinMap_I2S_WSEL);
Wolfgang Betz 1:f90318e0923b 252 SPIName i2s_fdpx = (SPIName)pinmap_peripheral(fdpx, PinMap_I2S_FDPX);
Wolfgang Betz 1:f90318e0923b 253
Wolfgang Betz 1:f90318e0923b 254 SPIName i2s_mclk = (SPIName)pinmap_peripheral(mclk, PinMap_I2S_MCLK);
Wolfgang Betz 1:f90318e0923b 255
Wolfgang Betz 1:f90318e0923b 256 SPIName i2s_merge1 = (SPIName)pinmap_merge(i2s_data, i2s_sclk);
Wolfgang Betz 1:f90318e0923b 257 SPIName i2s_merge2 = (SPIName)pinmap_merge(i2s_wsel, i2s_fdpx);
Wolfgang Betz 1:f90318e0923b 258
Wolfgang Betz 1:f90318e0923b 259 SPIName i2s_merge3 = (SPIName)pinmap_merge(i2s_merge1, i2s_merge2);
Wolfgang Betz 1:f90318e0923b 260 SPIName instance = (SPIName)pinmap_merge(i2s_merge3, i2s_mclk);
Wolfgang Betz 1:f90318e0923b 261 MBED_ASSERT(instance != (SPIName)NC);
Wolfgang Betz 1:f90318e0923b 262
Wolfgang Betz 1:f90318e0923b 263 // Enable I2S/SPI clock and set the right module number
Wolfgang Betz 1:f90318e0923b 264 switch(instance) {
Wolfgang Betz 1:f90318e0923b 265 #if defined(I2S1ext_BASE)
Wolfgang Betz 1:f90318e0923b 266 case SPI_1:
Wolfgang Betz 1:f90318e0923b 267 __SPI1_CLK_ENABLE();
Wolfgang Betz 1:f90318e0923b 268 obj->i2s.module = 0;
Wolfgang Betz 1:f90318e0923b 269 dma_dev = DMA_SPI1;
Wolfgang Betz 1:f90318e0923b 270 break;
Wolfgang Betz 1:f90318e0923b 271 #endif
Wolfgang Betz 1:f90318e0923b 272 #if defined(I2S2ext_BASE)
Wolfgang Betz 1:f90318e0923b 273 case SPI_2:
Wolfgang Betz 1:f90318e0923b 274 __SPI2_CLK_ENABLE();
Wolfgang Betz 1:f90318e0923b 275 obj->i2s.module = 1;
Wolfgang Betz 1:f90318e0923b 276 dma_dev = DMA_SPI2;
Wolfgang Betz 1:f90318e0923b 277 break;
Wolfgang Betz 1:f90318e0923b 278 #endif
Wolfgang Betz 1:f90318e0923b 279 #if defined(I2S3ext_BASE)
Wolfgang Betz 1:f90318e0923b 280 case SPI_3:
Wolfgang Betz 1:f90318e0923b 281 __SPI3_CLK_ENABLE();
Wolfgang Betz 1:f90318e0923b 282 obj->i2s.module = 2;
Wolfgang Betz 1:f90318e0923b 283 dma_dev = DMA_SPI3;
Wolfgang Betz 1:f90318e0923b 284 break;
Wolfgang Betz 1:f90318e0923b 285 #endif
Wolfgang Betz 1:f90318e0923b 286 #if defined(I2S4ext_BASE)
Wolfgang Betz 1:f90318e0923b 287 case SPI_4:
Wolfgang Betz 1:f90318e0923b 288 __SPI4_CLK_ENABLE();
Wolfgang Betz 1:f90318e0923b 289 obj->i2s.module = 3;
Wolfgang Betz 1:f90318e0923b 290 dma_dev = DMA_SPI4;
Wolfgang Betz 1:f90318e0923b 291 break;
Wolfgang Betz 1:f90318e0923b 292 #endif
Wolfgang Betz 1:f90318e0923b 293 #if defined(I2S5ext_BASE)
Wolfgang Betz 1:f90318e0923b 294 case SPI_5:
Wolfgang Betz 1:f90318e0923b 295 __SPI5_CLK_ENABLE();
Wolfgang Betz 1:f90318e0923b 296 obj->i2s.module = 4;
Wolfgang Betz 1:f90318e0923b 297 dma_dev = DMA_SPI5;
Wolfgang Betz 1:f90318e0923b 298 break;
Wolfgang Betz 1:f90318e0923b 299 #endif
Wolfgang Betz 1:f90318e0923b 300 default:
Wolfgang Betz 1:f90318e0923b 301 MBED_ASSERT(0);
Wolfgang Betz 1:f90318e0923b 302 break;
Wolfgang Betz 1:f90318e0923b 303 }
Wolfgang Betz 1:f90318e0923b 304
Wolfgang Betz 1:f90318e0923b 305 // Save DMA device
Wolfgang Betz 1:f90318e0923b 306 obj->dma.dma_device = dma_dev;
Wolfgang Betz 1:f90318e0923b 307
Wolfgang Betz 1:f90318e0923b 308 // Configure the I2S pins
Wolfgang Betz 1:f90318e0923b 309 pinmap_pinout(data, PinMap_I2S_DATA);
Wolfgang Betz 1:f90318e0923b 310 pinmap_pinout(wsel, PinMap_I2S_WSEL);
Wolfgang Betz 1:f90318e0923b 311 pinmap_pinout(sclk, PinMap_I2S_SCLK);
Wolfgang Betz 1:f90318e0923b 312 pinmap_pinout(fdpx, PinMap_I2S_FDPX);
Wolfgang Betz 1:f90318e0923b 313 pinmap_pinout(mclk, PinMap_I2S_MCLK);
Wolfgang Betz 1:f90318e0923b 314
Wolfgang Betz 1:f90318e0923b 315 obj->i2s.pin_wsel = wsel;
Wolfgang Betz 1:f90318e0923b 316 obj->i2s.pin_data = data;
Wolfgang Betz 1:f90318e0923b 317 obj->i2s.pin_sclk = sclk;
Wolfgang Betz 1:f90318e0923b 318 obj->i2s.pin_fdpx = fdpx;
Wolfgang Betz 1:f90318e0923b 319 obj->i2s.pin_mclk = mclk;
Wolfgang Betz 1:f90318e0923b 320
Wolfgang Betz 1:f90318e0923b 321 /* Configure PLLI2S */
Wolfgang Betz 1:f90318e0923b 322 static bool first_time = true;
Wolfgang Betz 1:f90318e0923b 323 if(first_time) {
Wolfgang Betz 1:f90318e0923b 324 RCC_PeriphCLKInitTypeDef PeriphClkInitStruct;
Wolfgang Betz 1:f90318e0923b 325
Wolfgang Betz 1:f90318e0923b 326 /* Get RTCClockSelection */
Wolfgang Betz 1:f90318e0923b 327 HAL_RCCEx_GetPeriphCLKConfig(&PeriphClkInitStruct);
Wolfgang Betz 1:f90318e0923b 328
Wolfgang Betz 1:f90318e0923b 329 /* Set default configuration */
Wolfgang Betz 1:f90318e0923b 330 PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_I2S;
Wolfgang Betz 1:f90318e0923b 331 PeriphClkInitStruct.PLLI2S.PLLI2SN = 271; // betzw: use values which are suggested in Table 90. of the
Wolfgang Betz 1:f90318e0923b 332 PeriphClkInitStruct.PLLI2S.PLLI2SR = 2; // reference manual for master clock enabled & 44100Hz
Wolfgang Betz 1:f90318e0923b 333 #ifdef NDEBUG
Wolfgang Betz 1:f90318e0923b 334 HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct);
Wolfgang Betz 1:f90318e0923b 335 #else
Wolfgang Betz 1:f90318e0923b 336 HAL_StatusTypeDef ret = HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct);
Wolfgang Betz 1:f90318e0923b 337 #endif
Wolfgang Betz 1:f90318e0923b 338 MBED_ASSERT(ret == HAL_OK);
Wolfgang Betz 1:f90318e0923b 339 first_time = false;
Wolfgang Betz 1:f90318e0923b 340 }
Wolfgang Betz 1:f90318e0923b 341
Wolfgang Betz 1:f90318e0923b 342 // initialize the handle for this master!
Wolfgang Betz 1:f90318e0923b 343 I2S_HandleTypeDef *handle = &I2sHandle[obj->i2s.module];
Wolfgang Betz 1:f90318e0923b 344
Wolfgang Betz 1:f90318e0923b 345 handle->Instance = (SPI_TypeDef *)(instance);
Wolfgang Betz 1:f90318e0923b 346 handle->Init.Mode = i2s_get_mode(mode, &dma_direction);
Wolfgang Betz 1:f90318e0923b 347 handle->Init.Standard = I2S_STANDARD_PCM_SHORT;
Wolfgang Betz 1:f90318e0923b 348 handle->Init.DataFormat = I2S_DATAFORMAT_16B;
Wolfgang Betz 1:f90318e0923b 349 handle->Init.MCLKOutput = I2S_MCLKOUTPUT_ENABLE; // betzw: always enable master clock to avoid frequency dis-alignment between I2S devices
Wolfgang Betz 1:f90318e0923b 350 handle->Init.AudioFreq = I2S_AUDIOFREQ_44K;
Wolfgang Betz 1:f90318e0923b 351 handle->Init.CPOL = I2S_CPOL_LOW;
Wolfgang Betz 1:f90318e0923b 352 handle->Init.ClockSource = I2S_CLOCK_PLL;
Wolfgang Betz 1:f90318e0923b 353 handle->Init.FullDuplexMode = (fdpx == NC) ? I2S_FULLDUPLEXMODE_DISABLE : I2S_FULLDUPLEXMODE_ENABLE;
Wolfgang Betz 1:f90318e0923b 354
Wolfgang Betz 1:f90318e0923b 355 // Save primary DMA direction
Wolfgang Betz 1:f90318e0923b 356 obj->dma.dma_direction = dma_direction;
Wolfgang Betz 1:f90318e0923b 357
Wolfgang Betz 1:f90318e0923b 358 DEBUG_PRINTF("I2S%u: Init\n", obj->i2s.module+1);
Wolfgang Betz 1:f90318e0923b 359
Wolfgang Betz 1:f90318e0923b 360 init_i2s(obj);
Wolfgang Betz 1:f90318e0923b 361 }
Wolfgang Betz 1:f90318e0923b 362
Wolfgang Betz 1:f90318e0923b 363 void i2s_free(i2s_t *obj)
Wolfgang Betz 1:f90318e0923b 364 {
Wolfgang Betz 1:f90318e0923b 365 // Reset I2S and disable clock
Wolfgang Betz 1:f90318e0923b 366 switch(obj->i2s.module) {
Wolfgang Betz 1:f90318e0923b 367 #if defined(I2S1ext_BASE)
Wolfgang Betz 1:f90318e0923b 368 case 0:
Wolfgang Betz 1:f90318e0923b 369 __SPI1_FORCE_RESET();
Wolfgang Betz 1:f90318e0923b 370 __SPI1_RELEASE_RESET();
Wolfgang Betz 1:f90318e0923b 371 __SPI1_CLK_DISABLE();
Wolfgang Betz 1:f90318e0923b 372 break;
Wolfgang Betz 1:f90318e0923b 373 #endif
Wolfgang Betz 1:f90318e0923b 374 #if defined(I2S2ext_BASE)
Wolfgang Betz 1:f90318e0923b 375 case 1:
Wolfgang Betz 1:f90318e0923b 376 __SPI2_FORCE_RESET();
Wolfgang Betz 1:f90318e0923b 377 __SPI2_RELEASE_RESET();
Wolfgang Betz 1:f90318e0923b 378 __SPI2_CLK_DISABLE();
Wolfgang Betz 1:f90318e0923b 379 break;
Wolfgang Betz 1:f90318e0923b 380 #endif
Wolfgang Betz 1:f90318e0923b 381 #if defined(I2S3ext_BASE)
Wolfgang Betz 1:f90318e0923b 382 case 2:
Wolfgang Betz 1:f90318e0923b 383 __SPI3_FORCE_RESET();
Wolfgang Betz 1:f90318e0923b 384 __SPI3_RELEASE_RESET();
Wolfgang Betz 1:f90318e0923b 385 __SPI3_CLK_DISABLE();
Wolfgang Betz 1:f90318e0923b 386 break;
Wolfgang Betz 1:f90318e0923b 387 #endif
Wolfgang Betz 1:f90318e0923b 388 #if defined(I2S4ext_BASE)
Wolfgang Betz 1:f90318e0923b 389 case 3:
Wolfgang Betz 1:f90318e0923b 390 __SPI4_FORCE_RESET();
Wolfgang Betz 1:f90318e0923b 391 __SPI4_RELEASE_RESET();
Wolfgang Betz 1:f90318e0923b 392 __SPI4_CLK_DISABLE();
Wolfgang Betz 1:f90318e0923b 393 break;
Wolfgang Betz 1:f90318e0923b 394 #endif
Wolfgang Betz 1:f90318e0923b 395 #if defined(I2S5ext_BASE)
Wolfgang Betz 1:f90318e0923b 396 case 4:
Wolfgang Betz 1:f90318e0923b 397 __SPI5_FORCE_RESET();
Wolfgang Betz 1:f90318e0923b 398 __SPI5_RELEASE_RESET();
Wolfgang Betz 1:f90318e0923b 399 __SPI5_CLK_DISABLE();
Wolfgang Betz 1:f90318e0923b 400 break;
Wolfgang Betz 1:f90318e0923b 401 #endif
Wolfgang Betz 1:f90318e0923b 402 default:
Wolfgang Betz 1:f90318e0923b 403 MBED_ASSERT(0);
Wolfgang Betz 1:f90318e0923b 404 break;
Wolfgang Betz 1:f90318e0923b 405 }
Wolfgang Betz 1:f90318e0923b 406
Wolfgang Betz 1:f90318e0923b 407 // betzw - TODO: what about 'PLLI2S'?!?
Wolfgang Betz 1:f90318e0923b 408 // for the moment we leave it enabled!
Wolfgang Betz 1:f90318e0923b 409
Wolfgang Betz 1:f90318e0923b 410 // Configure GPIOs
Wolfgang Betz 1:f90318e0923b 411 pin_function(obj->i2s.pin_wsel, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, 0));
Wolfgang Betz 1:f90318e0923b 412 pin_function(obj->i2s.pin_data, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, 0));
Wolfgang Betz 1:f90318e0923b 413 pin_function(obj->i2s.pin_sclk, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, 0));
Wolfgang Betz 1:f90318e0923b 414 pin_function(obj->i2s.pin_fdpx, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, 0));
Wolfgang Betz 1:f90318e0923b 415 pin_function(obj->i2s.pin_mclk, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, 0));
Wolfgang Betz 1:f90318e0923b 416
Wolfgang Betz 1:f90318e0923b 417 DEBUG_PRINTF("I2S%u: Free\n", obj->i2s.module+1);
Wolfgang Betz 1:f90318e0923b 418 }
Wolfgang Betz 1:f90318e0923b 419
Wolfgang Betz 1:f90318e0923b 420 void i2s_format(i2s_t *obj, int dbits, int fbits, int polarity)
Wolfgang Betz 1:f90318e0923b 421 {
Wolfgang Betz 1:f90318e0923b 422 I2S_HandleTypeDef *handle = &I2sHandle[obj->i2s.module];
Wolfgang Betz 1:f90318e0923b 423
Wolfgang Betz 1:f90318e0923b 424 // Save new values
Wolfgang Betz 1:f90318e0923b 425 if (fbits == 16) { // format MUST be 16B
Wolfgang Betz 1:f90318e0923b 426 handle->Init.DataFormat = I2S_DATAFORMAT_16B;
Wolfgang Betz 1:f90318e0923b 427 } else { // format may NOT be 16B
Wolfgang Betz 1:f90318e0923b 428 switch (dbits) {
Wolfgang Betz 1:f90318e0923b 429 case 16:
Wolfgang Betz 1:f90318e0923b 430 handle->Init.DataFormat = I2S_DATAFORMAT_16B_EXTENDED;
Wolfgang Betz 1:f90318e0923b 431 break;
Wolfgang Betz 1:f90318e0923b 432 case 24:
Wolfgang Betz 1:f90318e0923b 433 handle->Init.DataFormat = I2S_DATAFORMAT_24B;
Wolfgang Betz 1:f90318e0923b 434 break;
Wolfgang Betz 1:f90318e0923b 435 case 32:
Wolfgang Betz 1:f90318e0923b 436 default:
Wolfgang Betz 1:f90318e0923b 437 handle->Init.DataFormat = I2S_DATAFORMAT_32B;
Wolfgang Betz 1:f90318e0923b 438 break;
Wolfgang Betz 1:f90318e0923b 439 }
Wolfgang Betz 1:f90318e0923b 440 }
Wolfgang Betz 1:f90318e0923b 441
Wolfgang Betz 1:f90318e0923b 442 handle->Init.CPOL = (polarity == 0) ? I2S_CPOL_LOW : I2S_CPOL_HIGH;
Wolfgang Betz 1:f90318e0923b 443
Wolfgang Betz 1:f90318e0923b 444 DEBUG_PRINTF("I2S%u: Format: %u (%u, %u), %u (%u)\n", obj->i2s.module+1,
Wolfgang Betz 1:f90318e0923b 445 (unsigned int)handle->Init.DataFormat, (unsigned int)dbits, (unsigned int)fbits,
Wolfgang Betz 1:f90318e0923b 446 (unsigned int)handle->Init.CPOL, (unsigned int)polarity);
Wolfgang Betz 1:f90318e0923b 447
Wolfgang Betz 1:f90318e0923b 448 init_i2s(obj);
Wolfgang Betz 1:f90318e0923b 449 }
Wolfgang Betz 1:f90318e0923b 450
Wolfgang Betz 1:f90318e0923b 451 void i2s_set_mode(i2s_t *obj, i2s_mode_t mode)
Wolfgang Betz 1:f90318e0923b 452 {
Wolfgang Betz 1:f90318e0923b 453 uint8_t dma_direction;
Wolfgang Betz 1:f90318e0923b 454 I2S_HandleTypeDef *handle = &I2sHandle[obj->i2s.module];
Wolfgang Betz 1:f90318e0923b 455
Wolfgang Betz 1:f90318e0923b 456 handle->Init.Mode = i2s_get_mode(mode, &dma_direction);
Wolfgang Betz 1:f90318e0923b 457
Wolfgang Betz 1:f90318e0923b 458 // Save primary DMA direction
Wolfgang Betz 1:f90318e0923b 459 obj->dma.dma_direction = dma_direction;
Wolfgang Betz 1:f90318e0923b 460
Wolfgang Betz 1:f90318e0923b 461 DEBUG_PRINTF("I2S%u: Mode: %u (%u)\n", obj->i2s.module+1,
Wolfgang Betz 1:f90318e0923b 462 (unsigned int)handle->Init.Mode, (unsigned int)mode);
Wolfgang Betz 1:f90318e0923b 463
Wolfgang Betz 1:f90318e0923b 464 init_i2s(obj);
Wolfgang Betz 1:f90318e0923b 465 }
Wolfgang Betz 1:f90318e0923b 466
Wolfgang Betz 1:f90318e0923b 467 void i2s_set_protocol(i2s_t *obj, i2s_bitorder_t protocol)
Wolfgang Betz 1:f90318e0923b 468 {
Wolfgang Betz 1:f90318e0923b 469 I2S_HandleTypeDef *handle = &I2sHandle[obj->i2s.module];
Wolfgang Betz 1:f90318e0923b 470
Wolfgang Betz 1:f90318e0923b 471 switch (protocol) {
Wolfgang Betz 1:f90318e0923b 472 case PHILIPS:
Wolfgang Betz 1:f90318e0923b 473 handle->Init.Standard = I2S_STANDARD_PHILIPS;
Wolfgang Betz 1:f90318e0923b 474 break;
Wolfgang Betz 1:f90318e0923b 475 case MSB:
Wolfgang Betz 1:f90318e0923b 476 handle->Init.Standard = I2S_STANDARD_MSB;
Wolfgang Betz 1:f90318e0923b 477 break;
Wolfgang Betz 1:f90318e0923b 478 case LSB:
Wolfgang Betz 1:f90318e0923b 479 handle->Init.Standard = I2S_STANDARD_LSB;
Wolfgang Betz 1:f90318e0923b 480 break;
Wolfgang Betz 1:f90318e0923b 481 case PCM_SHORT:
Wolfgang Betz 1:f90318e0923b 482 handle->Init.Standard = I2S_STANDARD_PCM_SHORT;
Wolfgang Betz 1:f90318e0923b 483 break;
Wolfgang Betz 1:f90318e0923b 484 case PCM_LONG:
Wolfgang Betz 1:f90318e0923b 485 default:
Wolfgang Betz 1:f90318e0923b 486 handle->Init.Standard = I2S_STANDARD_PCM_LONG;
Wolfgang Betz 1:f90318e0923b 487 break;
Wolfgang Betz 1:f90318e0923b 488 }
Wolfgang Betz 1:f90318e0923b 489
Wolfgang Betz 1:f90318e0923b 490 DEBUG_PRINTF("I2S%u: Protocol: %u (%u)\n", obj->i2s.module+1,
Wolfgang Betz 1:f90318e0923b 491 (unsigned int)handle->Init.Standard, (unsigned int)protocol);
Wolfgang Betz 1:f90318e0923b 492
Wolfgang Betz 1:f90318e0923b 493 init_i2s(obj);
Wolfgang Betz 1:f90318e0923b 494 }
Wolfgang Betz 1:f90318e0923b 495
Wolfgang Betz 1:f90318e0923b 496 void i2s_audio_frequency(i2s_t *obj, uint32_t hz)
Wolfgang Betz 1:f90318e0923b 497 {
Wolfgang Betz 1:f90318e0923b 498 I2S_HandleTypeDef *handle = &I2sHandle[obj->i2s.module];
Wolfgang Betz 1:f90318e0923b 499
Wolfgang Betz 1:f90318e0923b 500 if (IS_I2S_AUDIO_FREQ(hz) && (hz != I2S_AUDIOFREQ_DEFAULT)) {
Wolfgang Betz 1:f90318e0923b 501 handle->Init.AudioFreq = hz;
Wolfgang Betz 1:f90318e0923b 502 } else if (hz < I2S_AUDIOFREQ_8K) {
Wolfgang Betz 1:f90318e0923b 503 handle->Init.AudioFreq = I2S_AUDIOFREQ_8K;
Wolfgang Betz 1:f90318e0923b 504 } else {
Wolfgang Betz 1:f90318e0923b 505 handle->Init.AudioFreq = I2S_AUDIOFREQ_192K;
Wolfgang Betz 1:f90318e0923b 506 }
Wolfgang Betz 1:f90318e0923b 507
Wolfgang Betz 1:f90318e0923b 508 DEBUG_PRINTF("I2S%u: Audio frequency: %u (%u)\n", obj->i2s.module+1,
Wolfgang Betz 1:f90318e0923b 509 (unsigned int)handle->Init.AudioFreq, (unsigned int)hz);
Wolfgang Betz 1:f90318e0923b 510
Wolfgang Betz 1:f90318e0923b 511 init_i2s(obj);
Wolfgang Betz 1:f90318e0923b 512 }
Wolfgang Betz 1:f90318e0923b 513
Wolfgang Betz 1:f90318e0923b 514 uint8_t i2s_get_module(i2s_t *obj)
Wolfgang Betz 1:f90318e0923b 515 {
Wolfgang Betz 1:f90318e0923b 516 return obj->i2s.module;
Wolfgang Betz 1:f90318e0923b 517 }
Wolfgang Betz 1:f90318e0923b 518
Wolfgang Betz 1:f90318e0923b 519 static void i2s_start_asynch_transfer(i2s_t *obj, transfer_type_t transfer_type,
Wolfgang Betz 1:f90318e0923b 520 void *tx, void *rx, int length)
Wolfgang Betz 1:f90318e0923b 521 {
Wolfgang Betz 1:f90318e0923b 522 I2S_HandleTypeDef *handle = &I2sHandle[obj->i2s.module];
Wolfgang Betz 1:f90318e0923b 523 obj->i2s.transfer_type = transfer_type;
Wolfgang Betz 1:f90318e0923b 524
Wolfgang Betz 1:f90318e0923b 525 // the HAL expects number of transfers instead of number of bytes
Wolfgang Betz 1:f90318e0923b 526 int words;
Wolfgang Betz 1:f90318e0923b 527 switch(handle->Init.DataFormat) {
Wolfgang Betz 1:f90318e0923b 528 case I2S_DATAFORMAT_16B:
Wolfgang Betz 1:f90318e0923b 529 case I2S_DATAFORMAT_16B_EXTENDED:
Wolfgang Betz 1:f90318e0923b 530 words = length / 2;
Wolfgang Betz 1:f90318e0923b 531 if(words > 0xFFFC) words = 0xFFFC; // truncate in order to respect max DMA length
Wolfgang Betz 1:f90318e0923b 532 break;
Wolfgang Betz 1:f90318e0923b 533 case I2S_DATAFORMAT_24B:
Wolfgang Betz 1:f90318e0923b 534 case I2S_DATAFORMAT_32B:
Wolfgang Betz 1:f90318e0923b 535 default:
Wolfgang Betz 1:f90318e0923b 536 words = length / 4;
Wolfgang Betz 1:f90318e0923b 537 if(words > 0x7FFC) words = 0x7FFC; // truncate in order to respect max DMA length
Wolfgang Betz 1:f90318e0923b 538 break;
Wolfgang Betz 1:f90318e0923b 539 }
Wolfgang Betz 1:f90318e0923b 540
Wolfgang Betz 1:f90318e0923b 541 // enable the right hal transfer
Wolfgang Betz 1:f90318e0923b 542 int rc = 0;
Wolfgang Betz 1:f90318e0923b 543 switch(transfer_type) {
Wolfgang Betz 1:f90318e0923b 544 case I2S_TRANSFER_TYPE_TXRX:
Wolfgang Betz 1:f90318e0923b 545 // enable the interrupts
Wolfgang Betz 1:f90318e0923b 546 NVIC_EnableIRQ(obj->dma.dma[DMA_TX]->dma_stream_irq);
Wolfgang Betz 1:f90318e0923b 547 NVIC_EnableIRQ(obj->dma.dma[DMA_RX]->dma_stream_irq);
Wolfgang Betz 1:f90318e0923b 548 // trigger DMA transfers
Wolfgang Betz 1:f90318e0923b 549 rc = HAL_I2SEx_TransmitReceive_DMA(handle, (uint16_t*)tx, (uint16_t*)rx, (uint16_t)words);
Wolfgang Betz 1:f90318e0923b 550 break;
Wolfgang Betz 1:f90318e0923b 551 case I2S_TRANSFER_TYPE_TX:
Wolfgang Betz 1:f90318e0923b 552 // enable the interrupt
Wolfgang Betz 1:f90318e0923b 553 NVIC_EnableIRQ(obj->dma.dma[DMA_TX]->dma_stream_irq);
Wolfgang Betz 1:f90318e0923b 554 // trigger DMA transfer
Wolfgang Betz 1:f90318e0923b 555 rc = HAL_I2S_Transmit_DMA(handle, (uint16_t*)tx, (uint16_t)words);
Wolfgang Betz 1:f90318e0923b 556 break;
Wolfgang Betz 1:f90318e0923b 557 case I2S_TRANSFER_TYPE_RX:
Wolfgang Betz 1:f90318e0923b 558 // enable the interrupt
Wolfgang Betz 1:f90318e0923b 559 NVIC_EnableIRQ(obj->dma.dma[DMA_RX]->dma_stream_irq);
Wolfgang Betz 1:f90318e0923b 560 // trigger DMA transfer
Wolfgang Betz 1:f90318e0923b 561 rc = HAL_I2S_Receive_DMA(handle, (uint16_t*)rx, (uint16_t)words);
Wolfgang Betz 1:f90318e0923b 562 break;
Wolfgang Betz 1:f90318e0923b 563 }
Wolfgang Betz 1:f90318e0923b 564
Wolfgang Betz 1:f90318e0923b 565 if (rc) {
Wolfgang Betz 1:f90318e0923b 566 DEBUG_PRINTF("I2S%u: RC=%d\n", obj->i2s.module+1, rc);
Wolfgang Betz 1:f90318e0923b 567 }
Wolfgang Betz 1:f90318e0923b 568
Wolfgang Betz 1:f90318e0923b 569 return;
Wolfgang Betz 1:f90318e0923b 570 }
Wolfgang Betz 1:f90318e0923b 571
Wolfgang Betz 1:f90318e0923b 572 // asynchronous API
Wolfgang Betz 1:f90318e0923b 573 void i2s_transfer(i2s_t *obj,
Wolfgang Betz 1:f90318e0923b 574 void *tx, int tx_length,
Wolfgang Betz 1:f90318e0923b 575 void *rx, int rx_length,
Wolfgang Betz 1:f90318e0923b 576 bool circular, i2s_dma_prio_t prio,
Wolfgang Betz 1:f90318e0923b 577 uint32_t handler_tx, uint32_t handler_rx, uint32_t event)
Wolfgang Betz 1:f90318e0923b 578 {
Wolfgang Betz 1:f90318e0923b 579 // check which use-case we have
Wolfgang Betz 1:f90318e0923b 580 bool use_tx = (tx != NULL && tx_length > 0);
Wolfgang Betz 1:f90318e0923b 581 bool use_rx = (rx != NULL && rx_length > 0);
Wolfgang Betz 1:f90318e0923b 582
Wolfgang Betz 1:f90318e0923b 583 // Init DMAs
Wolfgang Betz 1:f90318e0923b 584 dma_i2s_init(obj, &use_tx, &use_rx, circular, prio);
Wolfgang Betz 1:f90318e0923b 585
Wolfgang Betz 1:f90318e0923b 586 // don't do anything, if the buffers aren't valid
Wolfgang Betz 1:f90318e0923b 587 if (!use_tx && !use_rx)
Wolfgang Betz 1:f90318e0923b 588 return;
Wolfgang Betz 1:f90318e0923b 589
Wolfgang Betz 1:f90318e0923b 590 // copy the buffers to the I2S object
Wolfgang Betz 1:f90318e0923b 591 obj->tx_buff.buffer = tx;
Wolfgang Betz 1:f90318e0923b 592 obj->tx_buff.length = tx_length;
Wolfgang Betz 1:f90318e0923b 593 obj->tx_buff.pos = 0;
Wolfgang Betz 1:f90318e0923b 594 obj->tx_buff.width = 16;
Wolfgang Betz 1:f90318e0923b 595
Wolfgang Betz 1:f90318e0923b 596 obj->rx_buff.buffer = rx;
Wolfgang Betz 1:f90318e0923b 597 obj->rx_buff.length = rx_length;
Wolfgang Betz 1:f90318e0923b 598 obj->rx_buff.pos = 0;
Wolfgang Betz 1:f90318e0923b 599 obj->rx_buff.width = obj->tx_buff.width;
Wolfgang Betz 1:f90318e0923b 600
Wolfgang Betz 1:f90318e0923b 601 obj->i2s.event = event;
Wolfgang Betz 1:f90318e0923b 602
Wolfgang Betz 1:f90318e0923b 603 DEBUG_PRINTF("I2S%u: Transfer: %u, %u\n", obj->i2s.module+1, tx_length, rx_length);
Wolfgang Betz 1:f90318e0923b 604
Wolfgang Betz 1:f90318e0923b 605 // register the thunking handler
Wolfgang Betz 1:f90318e0923b 606 if(use_tx) {
Wolfgang Betz 1:f90318e0923b 607 NVIC_SetVector(obj->dma.dma[DMA_TX]->dma_stream_irq, handler_tx);
Wolfgang Betz 1:f90318e0923b 608 }
Wolfgang Betz 1:f90318e0923b 609 if(use_rx) {
Wolfgang Betz 1:f90318e0923b 610 NVIC_SetVector(obj->dma.dma[DMA_RX]->dma_stream_irq, handler_rx);
Wolfgang Betz 1:f90318e0923b 611 }
Wolfgang Betz 1:f90318e0923b 612
Wolfgang Betz 1:f90318e0923b 613 // enable the right hal transfer
Wolfgang Betz 1:f90318e0923b 614 if (use_tx && use_rx) {
Wolfgang Betz 1:f90318e0923b 615 int size = (tx_length < rx_length)? tx_length : rx_length;
Wolfgang Betz 1:f90318e0923b 616 i2s_start_asynch_transfer(obj, I2S_TRANSFER_TYPE_TXRX, tx, rx, size);
Wolfgang Betz 1:f90318e0923b 617 } else if (use_tx) {
Wolfgang Betz 1:f90318e0923b 618 i2s_start_asynch_transfer(obj, I2S_TRANSFER_TYPE_TX, tx, NULL, tx_length);
Wolfgang Betz 1:f90318e0923b 619 } else if (use_rx) {
Wolfgang Betz 1:f90318e0923b 620 i2s_start_asynch_transfer(obj, I2S_TRANSFER_TYPE_RX, NULL, rx, rx_length);
Wolfgang Betz 1:f90318e0923b 621 }
Wolfgang Betz 1:f90318e0923b 622 }
Wolfgang Betz 1:f90318e0923b 623
Wolfgang Betz 1:f90318e0923b 624 uint32_t i2s_irq_handler_asynch(i2s_t *obj, uint8_t direction)
Wolfgang Betz 1:f90318e0923b 625 {
Wolfgang Betz 1:f90318e0923b 626 direction = (direction == I2S_TX_EVENT) ? DMA_TX : DMA_RX;
Wolfgang Betz 1:f90318e0923b 627
Wolfgang Betz 1:f90318e0923b 628 // use the right instance
Wolfgang Betz 1:f90318e0923b 629 I2S_HandleTypeDef *i2s_handle = &I2sHandle[obj->i2s.module];
Wolfgang Betz 1:f90318e0923b 630 DMA_HandleTypeDef *dma_handle = (direction == DMA_TX) ? i2s_handle->hdmatx : i2s_handle->hdmarx;
Wolfgang Betz 1:f90318e0923b 631
Wolfgang Betz 1:f90318e0923b 632 MBED_ASSERT(dma_handle != NULL);
Wolfgang Betz 1:f90318e0923b 633
Wolfgang Betz 1:f90318e0923b 634 int event = 0;
Wolfgang Betz 1:f90318e0923b 635
Wolfgang Betz 1:f90318e0923b 636 // call the Cube handler, this will update the handle
Wolfgang Betz 1:f90318e0923b 637 HAL_DMA_IRQHandler(dma_handle);
Wolfgang Betz 1:f90318e0923b 638
Wolfgang Betz 1:f90318e0923b 639 switch(HAL_I2S_GetState(i2s_handle)) {
Wolfgang Betz 1:f90318e0923b 640 case HAL_I2S_STATE_READY: {
Wolfgang Betz 1:f90318e0923b 641 // adjust buffer positions (betzw - TODO: to be checked for DMA transfers!!!)
Wolfgang Betz 1:f90318e0923b 642 int tx_size = (i2s_handle->TxXferSize - i2s_handle->TxXferCount);
Wolfgang Betz 1:f90318e0923b 643 int rx_size = (i2s_handle->RxXferSize - i2s_handle->RxXferCount);
Wolfgang Betz 1:f90318e0923b 644
Wolfgang Betz 1:f90318e0923b 645 // take data format into consideration
Wolfgang Betz 1:f90318e0923b 646 switch(i2s_handle->Init.DataFormat) {
Wolfgang Betz 1:f90318e0923b 647 case I2S_DATAFORMAT_16B:
Wolfgang Betz 1:f90318e0923b 648 case I2S_DATAFORMAT_16B_EXTENDED:
Wolfgang Betz 1:f90318e0923b 649 tx_size *= 2;
Wolfgang Betz 1:f90318e0923b 650 rx_size *= 2;
Wolfgang Betz 1:f90318e0923b 651 break;
Wolfgang Betz 1:f90318e0923b 652 case I2S_DATAFORMAT_24B:
Wolfgang Betz 1:f90318e0923b 653 case I2S_DATAFORMAT_32B:
Wolfgang Betz 1:f90318e0923b 654 default:
Wolfgang Betz 1:f90318e0923b 655 tx_size *= 4;
Wolfgang Betz 1:f90318e0923b 656 rx_size *= 4;
Wolfgang Betz 1:f90318e0923b 657 break;
Wolfgang Betz 1:f90318e0923b 658 }
Wolfgang Betz 1:f90318e0923b 659
Wolfgang Betz 1:f90318e0923b 660 // adjust buffer positions
Wolfgang Betz 1:f90318e0923b 661 if (obj->i2s.transfer_type != I2S_TRANSFER_TYPE_RX) {
Wolfgang Betz 1:f90318e0923b 662 obj->tx_buff.pos += tx_size;
Wolfgang Betz 1:f90318e0923b 663 }
Wolfgang Betz 1:f90318e0923b 664 if (obj->i2s.transfer_type != I2S_TRANSFER_TYPE_TX) {
Wolfgang Betz 1:f90318e0923b 665 obj->rx_buff.pos += rx_size;
Wolfgang Betz 1:f90318e0923b 666 }
Wolfgang Betz 1:f90318e0923b 667
Wolfgang Betz 1:f90318e0923b 668 if (i2s_handle->TxXferCount > 0) {
Wolfgang Betz 1:f90318e0923b 669 DEBUG_PRINTF("I2S%u: TxXferCount: %u\n", obj->i2s.module+1, i2s_handle->TxXferCount);
Wolfgang Betz 1:f90318e0923b 670 }
Wolfgang Betz 1:f90318e0923b 671 if (i2s_handle->RxXferCount > 0) {
Wolfgang Betz 1:f90318e0923b 672 DEBUG_PRINTF("I2S%u: RxXferCount: %u\n", obj->i2s.module+1, i2s_handle->RxXferCount);
Wolfgang Betz 1:f90318e0923b 673 }
Wolfgang Betz 1:f90318e0923b 674 }
Wolfgang Betz 1:f90318e0923b 675 /* no break */
Wolfgang Betz 1:f90318e0923b 676
Wolfgang Betz 1:f90318e0923b 677 case HAL_I2S_STATE_BUSY_TX:
Wolfgang Betz 1:f90318e0923b 678 case HAL_I2S_STATE_BUSY_RX:
Wolfgang Betz 1:f90318e0923b 679 case HAL_I2S_STATE_BUSY_TX_RX: {
Wolfgang Betz 1:f90318e0923b 680 int error = HAL_I2S_GetError(i2s_handle);
Wolfgang Betz 1:f90318e0923b 681
Wolfgang Betz 1:f90318e0923b 682 if(error != HAL_I2S_ERROR_NONE) {
Wolfgang Betz 1:f90318e0923b 683 // something went wrong and the transfer has definitely completed
Wolfgang Betz 1:f90318e0923b 684 event = ((direction == DMA_TX) ? I2S_EVENT_TX_ERROR : I2S_EVENT_RX_ERROR) | I2S_EVENT_INTERNAL_TRANSFER_COMPLETE;
Wolfgang Betz 1:f90318e0923b 685
Wolfgang Betz 1:f90318e0923b 686 if (error & HAL_I2S_ERROR_OVR) {
Wolfgang Betz 1:f90318e0923b 687 // buffer overrun
Wolfgang Betz 1:f90318e0923b 688 event |= I2S_EVENT_RX_OVERFLOW;
Wolfgang Betz 1:f90318e0923b 689 }
Wolfgang Betz 1:f90318e0923b 690
Wolfgang Betz 1:f90318e0923b 691 if (error & HAL_I2S_ERROR_UDR) {
Wolfgang Betz 1:f90318e0923b 692 // buffer underrun
Wolfgang Betz 1:f90318e0923b 693 event |= I2S_EVENT_TX_UNDERRUN;
Wolfgang Betz 1:f90318e0923b 694 }
Wolfgang Betz 1:f90318e0923b 695
Wolfgang Betz 1:f90318e0923b 696 // cleanup DMA (after error)
Wolfgang Betz 1:f90318e0923b 697 dma_i2s_free(obj, direction);
Wolfgang Betz 1:f90318e0923b 698 } else { // no error detected
Wolfgang Betz 1:f90318e0923b 699 HAL_DMA_StateTypeDef dma_state = HAL_DMA_GetState(dma_handle);
Wolfgang Betz 1:f90318e0923b 700
Wolfgang Betz 1:f90318e0923b 701 switch(dma_state) {
Wolfgang Betz 1:f90318e0923b 702 case HAL_DMA_STATE_READY_HALF_MEM0:
Wolfgang Betz 1:f90318e0923b 703 case HAL_DMA_STATE_READY_HALF_MEM1:
Wolfgang Betz 1:f90318e0923b 704 event = ((direction == DMA_TX) ? I2S_EVENT_TX_HALF_COMPLETE : I2S_EVENT_RX_HALF_COMPLETE);
Wolfgang Betz 1:f90318e0923b 705 break;
Wolfgang Betz 1:f90318e0923b 706 case HAL_DMA_STATE_READY_MEM0:
Wolfgang Betz 1:f90318e0923b 707 case HAL_DMA_STATE_READY_MEM1:
Wolfgang Betz 1:f90318e0923b 708 event = ((direction == DMA_TX) ? I2S_EVENT_TX_COMPLETE : I2S_EVENT_RX_COMPLETE);
Wolfgang Betz 1:f90318e0923b 709
Wolfgang Betz 1:f90318e0923b 710 if(dma_handle->Init.Mode != DMA_CIRCULAR) {
Wolfgang Betz 1:f90318e0923b 711 if (!i2s_active(obj)) { // Check for full-duplex transfer complete!
Wolfgang Betz 1:f90318e0923b 712 event |= I2S_EVENT_INTERNAL_TRANSFER_COMPLETE;
Wolfgang Betz 1:f90318e0923b 713 }
Wolfgang Betz 1:f90318e0923b 714
Wolfgang Betz 1:f90318e0923b 715 // cleanup DMA (because we are done)
Wolfgang Betz 1:f90318e0923b 716 dma_i2s_free(obj, direction);
Wolfgang Betz 1:f90318e0923b 717 }
Wolfgang Betz 1:f90318e0923b 718 break;
Wolfgang Betz 1:f90318e0923b 719 default:
Wolfgang Betz 1:f90318e0923b 720 printf("betzw(%s, %d): dma_state=0x%x\r\n", __func__, __LINE__, (int)dma_state);
Wolfgang Betz 1:f90318e0923b 721 MBED_ASSERT(0);
Wolfgang Betz 1:f90318e0923b 722 break;
Wolfgang Betz 1:f90318e0923b 723 }
Wolfgang Betz 1:f90318e0923b 724 }
Wolfgang Betz 1:f90318e0923b 725 }
Wolfgang Betz 1:f90318e0923b 726 break;
Wolfgang Betz 1:f90318e0923b 727
Wolfgang Betz 1:f90318e0923b 728 default:
Wolfgang Betz 1:f90318e0923b 729 // nothing to do?!?
Wolfgang Betz 1:f90318e0923b 730 break;
Wolfgang Betz 1:f90318e0923b 731 }
Wolfgang Betz 1:f90318e0923b 732
Wolfgang Betz 1:f90318e0923b 733 if (event) DEBUG_PRINTF("I2S%u: Event: 0x%x\n", obj->i2s.module+1, event);
Wolfgang Betz 1:f90318e0923b 734
Wolfgang Betz 1:f90318e0923b 735 return (event & (obj->i2s.event | I2S_EVENT_INTERNAL_TRANSFER_COMPLETE));
Wolfgang Betz 1:f90318e0923b 736 }
Wolfgang Betz 1:f90318e0923b 737
Wolfgang Betz 1:f90318e0923b 738 uint8_t i2s_active(i2s_t *obj)
Wolfgang Betz 1:f90318e0923b 739 {
Wolfgang Betz 1:f90318e0923b 740 I2S_HandleTypeDef *handle = &I2sHandle[obj->i2s.module];
Wolfgang Betz 1:f90318e0923b 741 HAL_I2S_StateTypeDef state = HAL_I2S_GetState(handle);
Wolfgang Betz 1:f90318e0923b 742
Wolfgang Betz 1:f90318e0923b 743 switch(state) {
Wolfgang Betz 1:f90318e0923b 744 case HAL_I2S_STATE_RESET:
Wolfgang Betz 1:f90318e0923b 745 case HAL_I2S_STATE_READY:
Wolfgang Betz 1:f90318e0923b 746 case HAL_I2S_STATE_ERROR:
Wolfgang Betz 1:f90318e0923b 747 return 0;
Wolfgang Betz 1:f90318e0923b 748 default:
Wolfgang Betz 1:f90318e0923b 749 return -1;
Wolfgang Betz 1:f90318e0923b 750 }
Wolfgang Betz 1:f90318e0923b 751 }
Wolfgang Betz 1:f90318e0923b 752
Wolfgang Betz 1:f90318e0923b 753 void i2s_abort_asynch(i2s_t *obj)
Wolfgang Betz 1:f90318e0923b 754 {
Wolfgang Betz 1:f90318e0923b 755 I2S_HandleTypeDef *i2s_handle = &I2sHandle[obj->i2s.module];
Wolfgang Betz 1:f90318e0923b 756
Wolfgang Betz 1:f90318e0923b 757 // Stop transfer
Wolfgang Betz 1:f90318e0923b 758 HAL_I2S_DMAStop(i2s_handle);
Wolfgang Betz 1:f90318e0923b 759
Wolfgang Betz 1:f90318e0923b 760 if(obj->dma.dma[DMA_TX] != NULL) {
Wolfgang Betz 1:f90318e0923b 761 DMA_HandleTypeDef *dma_handle_tx = &DMaHandles[obj->i2s.module][DMA_TX];
Wolfgang Betz 1:f90318e0923b 762
Wolfgang Betz 1:f90318e0923b 763 // disable interrupt & free resource
Wolfgang Betz 1:f90318e0923b 764 dma_i2s_free(obj, DMA_TX);
Wolfgang Betz 1:f90318e0923b 765
Wolfgang Betz 1:f90318e0923b 766 //clean up
Wolfgang Betz 1:f90318e0923b 767 __HAL_DMA_DISABLE(dma_handle_tx);
Wolfgang Betz 1:f90318e0923b 768 HAL_DMA_DeInit(dma_handle_tx);
Wolfgang Betz 1:f90318e0923b 769 HAL_DMA_Init(dma_handle_tx);
Wolfgang Betz 1:f90318e0923b 770 __HAL_DMA_ENABLE(dma_handle_tx);
Wolfgang Betz 1:f90318e0923b 771 }
Wolfgang Betz 1:f90318e0923b 772 if(obj->dma.dma[DMA_RX] != NULL) {
Wolfgang Betz 1:f90318e0923b 773 DMA_HandleTypeDef *dma_handle_rx = &DMaHandles[obj->i2s.module][DMA_RX];
Wolfgang Betz 1:f90318e0923b 774
Wolfgang Betz 1:f90318e0923b 775 // disable interrupt & free resource
Wolfgang Betz 1:f90318e0923b 776 dma_i2s_free(obj, DMA_RX);
Wolfgang Betz 1:f90318e0923b 777
Wolfgang Betz 1:f90318e0923b 778 //clean up
Wolfgang Betz 1:f90318e0923b 779 __HAL_DMA_DISABLE(dma_handle_rx);
Wolfgang Betz 1:f90318e0923b 780 HAL_DMA_DeInit(dma_handle_rx);
Wolfgang Betz 1:f90318e0923b 781 HAL_DMA_Init(dma_handle_rx);
Wolfgang Betz 1:f90318e0923b 782 __HAL_DMA_ENABLE(dma_handle_rx);
Wolfgang Betz 1:f90318e0923b 783 }
Wolfgang Betz 1:f90318e0923b 784
Wolfgang Betz 1:f90318e0923b 785 // clean-up I2S
Wolfgang Betz 1:f90318e0923b 786 __HAL_I2S_DISABLE(i2s_handle);
Wolfgang Betz 1:f90318e0923b 787 HAL_I2S_DeInit(i2s_handle);
Wolfgang Betz 1:f90318e0923b 788 HAL_I2S_Init(i2s_handle);
Wolfgang Betz 1:f90318e0923b 789 __HAL_I2S_ENABLE(i2s_handle);
Wolfgang Betz 1:f90318e0923b 790 }
Wolfgang Betz 1:f90318e0923b 791
Wolfgang Betz 1:f90318e0923b 792 #endif