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:
targets/TARGET_STM/stm_i2s_api.c@1:f90318e0923b, 2016-11-29 (annotated)
- 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?
User | Revision | Line number | New 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 |