From fbbe29b691546078caf04ac10d634f7f106174e2 Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 9 Feb 2022 21:33:58 +1100 Subject: [PATCH 1/8] stm32/machine_i2s: Support I2S passive mode. Signed-off-by: Damien George --- ports/stm32/machine_i2s.c | 43 ++++++++++++++++++++++++++------------- 1 file changed, 29 insertions(+), 14 deletions(-) diff --git a/ports/stm32/machine_i2s.c b/ports/stm32/machine_i2s.c index 31b7d14bfd4c1..6203a71486c16 100644 --- a/ports/stm32/machine_i2s.c +++ b/ports/stm32/machine_i2s.c @@ -526,7 +526,7 @@ STATIC bool i2s_init(machine_i2s_obj_t *self) { self->hi2s.Instance = I2S1; __SPI1_CLK_ENABLE(); // configure DMA streams - if (self->mode == I2S_MODE_MASTER_RX) { + if (self->mode == I2S_MODE_MASTER_RX || self->mode == I2S_MODE_SLAVE_RX) { self->dma_descr_rx = &dma_I2S_1_RX; } else { self->dma_descr_tx = &dma_I2S_1_TX; @@ -535,7 +535,7 @@ STATIC bool i2s_init(machine_i2s_obj_t *self) { self->hi2s.Instance = I2S2; __SPI2_CLK_ENABLE(); // configure DMA streams - if (self->mode == I2S_MODE_MASTER_RX) { + if (self->mode == I2S_MODE_MASTER_RX || self->mode == I2S_MODE_SLAVE_RX) { self->dma_descr_rx = &dma_I2S_2_RX; } else { self->dma_descr_tx = &dma_I2S_2_TX; @@ -570,7 +570,7 @@ STATIC bool i2s_init(machine_i2s_obj_t *self) { if (HAL_I2S_Init(&self->hi2s) == HAL_OK) { // Reset and initialize Tx and Rx DMA channels - if (self->mode == I2S_MODE_MASTER_RX) { + if (self->mode == I2S_MODE_MASTER_RX || self->mode == I2S_MODE_SLAVE_RX) { dma_invalidate_channel(self->dma_descr_rx); dma_init(&self->hdma_rx, self->dma_descr_rx, DMA_PERIPH_TO_MEMORY, &self->hi2s); self->hi2s.hdmarx = &self->hdma_rx; @@ -691,7 +691,7 @@ STATIC void machine_i2s_init_helper(machine_i2s_obj_t *self, size_t n_pos_args, { MP_QSTR_mode, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = -1} }, { MP_QSTR_bits, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = -1} }, { MP_QSTR_format, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = -1} }, - { MP_QSTR_rate, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = -1} }, + { MP_QSTR_rate, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, { MP_QSTR_ibuf, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = -1} }, }; @@ -740,7 +740,9 @@ STATIC void machine_i2s_init_helper(machine_i2s_obj_t *self, size_t n_pos_args, // is Mode valid? uint16_t i2s_mode = args[ARG_mode].u_int; if ((i2s_mode != (I2S_MODE_MASTER_RX)) && - (i2s_mode != (I2S_MODE_MASTER_TX))) { + (i2s_mode != (I2S_MODE_MASTER_TX)) && + (i2s_mode != (I2S_MODE_SLAVE_RX)) && + (i2s_mode != (I2S_MODE_SLAVE_TX))) { mp_raise_ValueError(MP_ERROR_TEXT("invalid mode")); } @@ -777,7 +779,7 @@ STATIC void machine_i2s_init_helper(machine_i2s_obj_t *self, size_t n_pos_args, self->mode = i2s_mode; self->bits = i2s_bits; self->format = i2s_format; - self->rate = args[ARG_rate].u_int; + self->rate = -1; self->ibuf = ring_buffer_len; self->callback_for_non_blocking = MP_OBJ_NULL; self->non_blocking_descriptor.copy_in_progress = false; @@ -788,10 +790,19 @@ STATIC void machine_i2s_init_helper(machine_i2s_obj_t *self, size_t n_pos_args, init->Standard = I2S_STANDARD_PHILIPS; init->DataFormat = get_dma_bits(self->mode, self->bits); init->MCLKOutput = I2S_MCLKOUTPUT_DISABLE; - init->AudioFreq = args[ARG_rate].u_int; + init->AudioFreq = I2S_AUDIOFREQ_DEFAULT; init->CPOL = I2S_CPOL_LOW; init->ClockSource = I2S_CLOCK_PLL; + // set rate if not in passive mode + if (i2s_mode == I2S_MODE_MASTER_TX || i2s_mode == I2S_MODE_MASTER_RX) { + self->rate = args[ARG_rate].u_int; + if (self->rate < 0) { + mp_raise_ValueError(MP_ERROR_TEXT("rate required")); + } + init->AudioFreq = args[ARG_rate].u_int; + } + // init the I2S bus if (!i2s_init(self)) { mp_raise_msg_varg(&mp_type_OSError, MP_ERROR_TEXT("I2S init failed")); @@ -806,7 +817,7 @@ STATIC void machine_i2s_init_helper(machine_i2s_obj_t *self, size_t n_pos_args, } HAL_StatusTypeDef status; - if (self->mode == I2S_MODE_MASTER_TX) { + if (self->mode == I2S_MODE_MASTER_TX || self->mode == I2S_MODE_SLAVE_TX) { status = HAL_I2S_Transmit_DMA(&self->hi2s, (void *)self->dma_buffer_dcache_aligned, number_of_samples); } else { // RX status = HAL_I2S_Receive_DMA(&self->hi2s, (void *)self->dma_buffer_dcache_aligned, number_of_samples); @@ -824,16 +835,18 @@ STATIC void machine_i2s_print(const mp_print_t *print, mp_obj_t self_in, mp_prin "ws="MP_HAL_PIN_FMT ",\n" "sd="MP_HAL_PIN_FMT ",\n" "mode=%u,\n" - "bits=%u, format=%u,\n" - "rate=%d, ibuf=%d)", + "bits=%u, format=%u,\n", self->i2s_id, mp_hal_pin_name(self->sck), mp_hal_pin_name(self->ws), mp_hal_pin_name(self->sd), self->mode, - self->bits, self->format, - self->rate, self->ibuf + self->bits, self->format ); + if (self->rate > 0) { + mp_printf(print, "rate=%d, ", self->rate); + } + mp_printf(print, "ibuf=%d)", self->ibuf); } STATIC mp_obj_t machine_i2s_make_new(const mp_obj_type_t *type, size_t n_pos_args, size_t n_kw_args, const mp_obj_t *args) { @@ -1000,6 +1013,8 @@ STATIC const mp_rom_map_elem_t machine_i2s_locals_dict_table[] = { // Constants { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_INT(I2S_MODE_MASTER_RX) }, { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_INT(I2S_MODE_MASTER_TX) }, + { MP_ROM_QSTR(MP_QSTR_RX_PASSIVE), MP_ROM_INT(I2S_MODE_SLAVE_RX) }, + { MP_ROM_QSTR(MP_QSTR_TX_PASSIVE), MP_ROM_INT(I2S_MODE_SLAVE_TX) }, { MP_ROM_QSTR(MP_QSTR_STEREO), MP_ROM_INT(STEREO) }, { MP_ROM_QSTR(MP_QSTR_MONO), MP_ROM_INT(MONO) }, }; @@ -1008,7 +1023,7 @@ MP_DEFINE_CONST_DICT(machine_i2s_locals_dict, machine_i2s_locals_dict_table); STATIC mp_uint_t machine_i2s_stream_read(mp_obj_t self_in, void *buf_in, mp_uint_t size, int *errcode) { machine_i2s_obj_t *self = MP_OBJ_TO_PTR(self_in); - if (self->mode != I2S_MODE_MASTER_RX) { + if (self->mode != I2S_MODE_MASTER_RX && self->mode != I2S_MODE_SLAVE_RX) { *errcode = MP_EPERM; return MP_STREAM_ERROR; } @@ -1041,7 +1056,7 @@ STATIC mp_uint_t machine_i2s_stream_read(mp_obj_t self_in, void *buf_in, mp_uint STATIC mp_uint_t machine_i2s_stream_write(mp_obj_t self_in, const void *buf_in, mp_uint_t size, int *errcode) { machine_i2s_obj_t *self = MP_OBJ_TO_PTR(self_in); - if (self->mode != I2S_MODE_MASTER_TX) { + if (self->mode != I2S_MODE_MASTER_TX && self->mode != I2S_MODE_SLAVE_TX) { *errcode = MP_EPERM; return MP_STREAM_ERROR; } From f4afbffeb7cbf9925b1059f3e8d1341b8af67864 Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 23 Mar 2022 15:21:03 +1100 Subject: [PATCH 2/8] stm32/machine_i2s: Set FullDuplexMode to disabled on F4. Signed-off-by: Damien George --- ports/stm32/machine_i2s.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ports/stm32/machine_i2s.c b/ports/stm32/machine_i2s.c index 6203a71486c16..6f7bbd27b77f3 100644 --- a/ports/stm32/machine_i2s.c +++ b/ports/stm32/machine_i2s.c @@ -793,6 +793,9 @@ STATIC void machine_i2s_init_helper(machine_i2s_obj_t *self, size_t n_pos_args, init->AudioFreq = I2S_AUDIOFREQ_DEFAULT; init->CPOL = I2S_CPOL_LOW; init->ClockSource = I2S_CLOCK_PLL; + #if defined(STM32F4) + init->FullDuplexMode = I2S_FULLDUPLEXMODE_DISABLE; + #endif // set rate if not in passive mode if (i2s_mode == I2S_MODE_MASTER_TX || i2s_mode == I2S_MODE_MASTER_RX) { From 86eb6bd90d261de97317982d46fe32f33cfc5aba Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 25 Mar 2022 14:29:48 +1100 Subject: [PATCH 3/8] stm32/machine_i2s: Allow I2S.deinit to be called multiple times. In particular, it is called by the constructor if the instance already exists. So if the previous instance was deinit'd then it will be deinit'd a second time. Signed-off-by: Damien George --- ports/stm32/machine_i2s.c | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/ports/stm32/machine_i2s.c b/ports/stm32/machine_i2s.c index 6f7bbd27b77f3..e387874a6fcce 100644 --- a/ports/stm32/machine_i2s.c +++ b/ports/stm32/machine_i2s.c @@ -900,24 +900,26 @@ STATIC mp_obj_t machine_i2s_init(size_t n_pos_args, const mp_obj_t *pos_args, mp STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_i2s_init_obj, 1, machine_i2s_init); STATIC mp_obj_t machine_i2s_deinit(mp_obj_t self_in) { - machine_i2s_obj_t *self = MP_OBJ_TO_PTR(self_in); - dma_deinit(self->dma_descr_tx); - dma_deinit(self->dma_descr_rx); - HAL_I2S_DeInit(&self->hi2s); - - if (self->hi2s.Instance == I2S1) { - __SPI1_FORCE_RESET(); - __SPI1_RELEASE_RESET(); - __SPI1_CLK_DISABLE(); - } else if (self->hi2s.Instance == I2S2) { - __SPI2_FORCE_RESET(); - __SPI2_RELEASE_RESET(); - __SPI2_CLK_DISABLE(); - } + if (self->ring_buffer_storage != NULL) { + dma_deinit(self->dma_descr_tx); + dma_deinit(self->dma_descr_rx); + HAL_I2S_DeInit(&self->hi2s); + + if (self->hi2s.Instance == I2S1) { + __SPI1_FORCE_RESET(); + __SPI1_RELEASE_RESET(); + __SPI1_CLK_DISABLE(); + } else if (self->hi2s.Instance == I2S2) { + __SPI2_FORCE_RESET(); + __SPI2_RELEASE_RESET(); + __SPI2_CLK_DISABLE(); + } - m_free(self->ring_buffer_storage); + m_free(self->ring_buffer_storage); + self->ring_buffer_storage = NULL; + } return mp_const_none; } From 6c41da429e88946179896bfb831a6f91149fc60c Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 25 Mar 2022 14:31:00 +1100 Subject: [PATCH 4/8] tests/multi_machine: Add a multi-test for machine.I2S. Signed-off-by: Damien George --- tests/multi_machine/i2s_data_transfer.py | 127 ++++++++++++ tests/multi_machine/i2s_data_transfer.py.exp | 193 +++++++++++++++++++ 2 files changed, 320 insertions(+) create mode 100644 tests/multi_machine/i2s_data_transfer.py create mode 100644 tests/multi_machine/i2s_data_transfer.py.exp diff --git a/tests/multi_machine/i2s_data_transfer.py b/tests/multi_machine/i2s_data_transfer.py new file mode 100644 index 0000000000000..b4f7b44cb3858 --- /dev/null +++ b/tests/multi_machine/i2s_data_transfer.py @@ -0,0 +1,127 @@ +# Test machine.I2S on PYB/PYBD +# +# Writes some bytes over I2S and checks they are received by the other device. +# Requires wiring up WS, SCK, SD pins between two devices. + +import os +from machine import Pin, I2S + +# Configure pins based on the board. +if "F405" in os.uname().machine: + i2s_id = 2 + ws_pin = Pin("Y5") + sck_pin = Pin("Y6") + sd_pin = Pin("Y8") +else: + i2s_id = 1 + ws_pin = Pin("X5") + sck_pin = Pin("X6") + sd_pin = Pin("X8") + +TEST_BYTES = b"0123456789ABCDEF" +RATE = 8000 # frames/sec + +def buf_len(bits_per_sample, frame_format): + if frame_format == I2S.MONO: + channels = 1 + else: + channels = 2 + bits_per_frame = bits_per_sample * channels + buf_len_100ms = bits_per_frame // 8 * RATE // 10 + assert buf_len_100ms % len(TEST_BYTES) == 0 + return buf_len_100ms + +def test_tx(mode, bits_per_sample, frame_format, num_tx): + i2s = I2S( + i2s_id, + sck=sck_pin, + ws=ws_pin, + sd=sd_pin, + mode=mode, + bits=bits_per_sample, + format=frame_format, + rate=RATE, + ibuf=200, + ) + + data = TEST_BYTES * (buf_len(bits_per_sample, frame_format) // len(TEST_BYTES)) + print("tx start") + for i in range(num_tx): + n = i2s.write(data) + print("write", n) + print("tx end") + i2s.deinit() + + +def test_rx(mode, bits_per_sample, frame_format, num_rx, num_rx_extra, expected): + i2s = I2S( + i2s_id, + sck=sck_pin, + ws=ws_pin, + sd=sd_pin, + mode=mode, + bits=bits_per_sample, + format=frame_format, + rate=RATE, + ibuf=200, + ) + + buf = bytearray(buf_len(bits_per_sample, frame_format)) + wanted_bytes = expected * 8 + + print("rx start") + + for _ in range(num_rx): + n = i2s.readinto(buf) + if wanted_bytes in buf: + print("read", n, True) + else: + print("read", n, buf[:16], buf[-16:]) + + # Extra reads for the case we are driving the clock, so the passive side finishes. + for _ in range(num_rx_extra): + i2s.readinto(buf) + + print("rx end") + + i2s.deinit() + + +def instance0(): + multitest.next() + for bits_per_sample, frame_format, expected in ( + # TX and RX transfer full 32-bit stereo + (32, I2S.STEREO, b"0123456789ABCDEF0123456789ABCDEF"), + # TX writes different formats, RX receives 32-bit stereo + (32, I2S.STEREO, b"012301234567456789AB89ABCDEFCDEF"), + (32, I2S.STEREO, b"23016745AB89EFCD23016745AB89EFCD"), + (32, I2S.STEREO, b"01012323454567678989ABABCDCDEFEF"), # 16-bit mono (L=R) + # TX writes 32-bit stereo, RX receives different formats + (32, I2S.MONO, b"012389AB012389AB012389AB012389AB"), # 32-bit, L channel only + (16, I2S.STEREO, b"014589CD014589CD014589CD014589CD"), + (16, I2S.MONO, b"23AB23AB23AB23AB23AB23AB23AB23AB"), + ): + test_rx(I2S.RX_PASSIVE, bits_per_sample, frame_format, 4, 0, expected) + multitest.wait("tx done") + test_rx(I2S.RX, bits_per_sample, frame_format, 4, 1, expected) + multitest.broadcast("rx done") + + +def instance1(): + multitest.next() + for bits_per_sample, frame_format, num_tx in ( + # TX and RX transfer full 32-bit stereo + (32, I2S.STEREO, 4), + # TX writes different formats, RX receives 32-bit stereo + (32, I2S.MONO, 4), + (16, I2S.STEREO, 8), + (16, I2S.MONO, 8), + # TX writes 32-bit stereo, RX receives different formats + (32, I2S.STEREO, 4), + (32, I2S.STEREO, 4), + (32, I2S.STEREO, 4), + ): + test_tx(I2S.TX, bits_per_sample, frame_format, num_tx + 1) + multitest.broadcast("tx done") + test_tx(I2S.TX_PASSIVE, bits_per_sample, frame_format, num_tx) + multitest.wait("rx done") diff --git a/tests/multi_machine/i2s_data_transfer.py.exp b/tests/multi_machine/i2s_data_transfer.py.exp new file mode 100644 index 0000000000000..6b20eebfe327d --- /dev/null +++ b/tests/multi_machine/i2s_data_transfer.py.exp @@ -0,0 +1,193 @@ +--- instance0 --- +rx start +read 6400 True +read 6400 True +read 6400 True +read 6400 True +rx end +rx start +read 6400 True +read 6400 True +read 6400 True +read 6400 True +rx end +rx start +read 6400 True +read 6400 True +read 6400 True +read 6400 True +rx end +rx start +read 6400 True +read 6400 True +read 6400 True +read 6400 True +rx end +rx start +read 6400 True +read 6400 True +read 6400 True +read 6400 True +rx end +rx start +read 6400 True +read 6400 True +read 6400 True +read 6400 True +rx end +rx start +read 6400 True +read 6400 True +read 6400 True +read 6400 True +rx end +rx start +read 6400 True +read 6400 True +read 6400 True +read 6400 True +rx end +rx start +read 3200 True +read 3200 True +read 3200 True +read 3200 True +rx end +rx start +read 3200 True +read 3200 True +read 3200 True +read 3200 True +rx end +rx start +read 3200 True +read 3200 True +read 3200 True +read 3200 True +rx end +rx start +read 3200 True +read 3200 True +read 3200 True +read 3200 True +rx end +rx start +read 1600 True +read 1600 True +read 1600 True +read 1600 True +rx end +rx start +read 1600 True +read 1600 True +read 1600 True +read 1600 True +rx end +--- instance1 --- +tx start +write 6400 +write 6400 +write 6400 +write 6400 +write 6400 +tx end +tx start +write 6400 +write 6400 +write 6400 +write 6400 +tx end +tx start +write 3200 +write 3200 +write 3200 +write 3200 +write 3200 +tx end +tx start +write 3200 +write 3200 +write 3200 +write 3200 +tx end +tx start +write 3200 +write 3200 +write 3200 +write 3200 +write 3200 +write 3200 +write 3200 +write 3200 +write 3200 +tx end +tx start +write 3200 +write 3200 +write 3200 +write 3200 +write 3200 +write 3200 +write 3200 +write 3200 +tx end +tx start +write 1600 +write 1600 +write 1600 +write 1600 +write 1600 +write 1600 +write 1600 +write 1600 +write 1600 +tx end +tx start +write 1600 +write 1600 +write 1600 +write 1600 +write 1600 +write 1600 +write 1600 +write 1600 +tx end +tx start +write 6400 +write 6400 +write 6400 +write 6400 +write 6400 +tx end +tx start +write 6400 +write 6400 +write 6400 +write 6400 +tx end +tx start +write 6400 +write 6400 +write 6400 +write 6400 +write 6400 +tx end +tx start +write 6400 +write 6400 +write 6400 +write 6400 +tx end +tx start +write 6400 +write 6400 +write 6400 +write 6400 +write 6400 +tx end +tx start +write 6400 +write 6400 +write 6400 +write 6400 +tx end From 3c1ef0f3b7a715e54ea2a7090f549d7a876c12db Mon Sep 17 00:00:00 2001 From: Damien George Date: Sat, 26 Mar 2022 00:07:19 +1100 Subject: [PATCH 5/8] stm32/machine_i2s: Fix 16-bit stereo i2s_frame_map. Signed-off-by: Damien George --- ports/stm32/machine_i2s.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ports/stm32/machine_i2s.c b/ports/stm32/machine_i2s.c index e387874a6fcce..349d07c96c57b 100644 --- a/ports/stm32/machine_i2s.c +++ b/ports/stm32/machine_i2s.c @@ -156,10 +156,10 @@ STATIC mp_obj_t machine_i2s_deinit(mp_obj_t self_in); // from DMA memory (32-bit stereo) to the format specified // in the I2S constructor. e.g. 16-bit mono STATIC const int8_t i2s_frame_map[NUM_I2S_USER_FORMATS][I2S_RX_FRAME_SIZE_IN_BYTES] = { - { 0, 1, -1, -1, -1, -1, -1, -1 }, // Mono, 16-bits - { 2, 3, 0, 1, -1, -1, -1, -1 }, // Mono, 32-bits - { 0, 1, 4, 5, -1, -1, -1, -1 }, // Stereo, 16-bits - { 2, 3, 0, 1, 6, 7, 4, 5 }, // Stereo, 32-bits + { 0, 1, -1, -1, -1, -1, -1, -1 }, // Mono, 16-bits + { 2, 3, 0, 1, -1, -1, -1, -1 }, // Mono, 32-bits + { -1, -1, 0, 1, -1, -1, 2, 3 }, // Stereo, 16-bits + { 2, 3, 0, 1, 6, 7, 4, 5 }, // Stereo, 32-bits }; void machine_i2s_init0() { From 7a84fc465990e99e77667003a01eedfc51d43fe2 Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 8 Feb 2022 00:33:44 +1100 Subject: [PATCH 6/8] stm32/machine_i2s: Add support for I2S on H7 MCUs. Master TX is tested, in blocking and non-blocking IO mode. Signed-off-by: Damien George --- ports/stm32/Makefile | 2 +- ports/stm32/boards/make-pins.py | 2 +- ports/stm32/boards/stm32h7xx_hal_conf_base.h | 1 + ports/stm32/dma.c | 10 +++++ ports/stm32/machine_i2s.c | 40 ++++++++++++++++++-- ports/stm32/pin_defs_stm32.h | 2 + 6 files changed, 52 insertions(+), 5 deletions(-) diff --git a/ports/stm32/Makefile b/ports/stm32/Makefile index 3083c99570e9c..209b2b4ca8860 100644 --- a/ports/stm32/Makefile +++ b/ports/stm32/Makefile @@ -412,7 +412,7 @@ endif endif endif -ifeq ($(MCU_SERIES),$(filter $(MCU_SERIES),f0 f4 f7 l0)) +ifeq ($(MCU_SERIES),$(filter $(MCU_SERIES),f0 f4 f7 h7 l0)) HAL_SRC_C += $(addprefix $(STM32LIB_HAL_BASE)/Src/stm32$(MCU_SERIES)xx_,\ hal_i2s.c \ ) diff --git a/ports/stm32/boards/make-pins.py b/ports/stm32/boards/make-pins.py index 4e895f8f60407..3a3541087042d 100755 --- a/ports/stm32/boards/make-pins.py +++ b/ports/stm32/boards/make-pins.py @@ -56,7 +56,7 @@ SUPPORTED_FN = { "TIM": ["CH1", "CH2", "CH3", "CH4", "CH1N", "CH2N", "CH3N", "CH1_ETR", "ETR", "BKIN"], "I2C": ["SDA", "SCL"], - "I2S": ["CK", "MCK", "SD", "WS", "EXTSD"], + "I2S": ["CK", "MCK", "SD", "SDO", "SDI", "WS", "EXTSD"], "USART": ["RX", "TX", "CTS", "RTS", "CK"], "UART": ["RX", "TX", "CTS", "RTS"], "LPUART": ["RX", "TX", "CTS", "RTS"], diff --git a/ports/stm32/boards/stm32h7xx_hal_conf_base.h b/ports/stm32/boards/stm32h7xx_hal_conf_base.h index 08928ed5933cd..4193acf57eb1c 100644 --- a/ports/stm32/boards/stm32h7xx_hal_conf_base.h +++ b/ports/stm32/boards/stm32h7xx_hal_conf_base.h @@ -57,6 +57,7 @@ #include "stm32h7xx_ll_lpuart.h" #include "stm32h7xx_ll_pwr.h" #include "stm32h7xx_ll_rtc.h" +#include "stm32h7xx_ll_spi.h" #include "stm32h7xx_ll_usart.h" // Enable various HAL modules diff --git a/ports/stm32/dma.c b/ports/stm32/dma.c index cb8e555df4b95..d16160f60941d 100644 --- a/ports/stm32/dma.c +++ b/ports/stm32/dma.c @@ -612,6 +612,10 @@ const dma_descr_t dma_I2C_3_RX = { DMA1_Stream2, DMA_REQUEST_I2C3_RX, dma_id_2, const dma_descr_t dma_I2C_2_RX = { DMA1_Stream2, DMA_REQUEST_I2C2_RX, dma_id_2, &dma_init_struct_spi_i2c }; const dma_descr_t dma_SPI_2_RX = { DMA1_Stream3, DMA_REQUEST_SPI2_RX, dma_id_3, &dma_init_struct_spi_i2c }; const dma_descr_t dma_SPI_2_TX = { DMA1_Stream4, DMA_REQUEST_SPI2_TX, dma_id_4, &dma_init_struct_spi_i2c }; +#if MICROPY_HW_ENABLE_I2S +const dma_descr_t dma_I2S_2_RX = { DMA1_Stream3, DMA_REQUEST_SPI2_RX, dma_id_3, &dma_init_struct_i2s }; +const dma_descr_t dma_I2S_2_TX = { DMA1_Stream4, DMA_REQUEST_SPI2_TX, dma_id_4, &dma_init_struct_i2s }; +#endif const dma_descr_t dma_I2C_3_TX = { DMA1_Stream4, DMA_REQUEST_I2C3_TX, dma_id_4, &dma_init_struct_spi_i2c }; const dma_descr_t dma_I2C_4_TX = { DMA1_Stream5, BDMA_REQUEST_I2C4_TX, dma_id_5, &dma_init_struct_spi_i2c }; #if defined(MICROPY_HW_ENABLE_DAC) && MICROPY_HW_ENABLE_DAC @@ -627,12 +631,18 @@ const dma_descr_t dma_I2C_2_TX = { DMA1_Stream7, DMA_REQUEST_I2C2_TX, dma_id_7, const dma_descr_t dma_DCMI_0 = { DMA2_Stream1, DMA_REQUEST_DCMI, dma_id_9, &dma_init_struct_dcmi }; #endif const dma_descr_t dma_SPI_1_RX = { DMA2_Stream2, DMA_REQUEST_SPI1_RX, dma_id_10, &dma_init_struct_spi_i2c }; +#if MICROPY_HW_ENABLE_I2S +const dma_descr_t dma_I2S_1_RX = { DMA2_Stream2, DMA_REQUEST_SPI1_RX, dma_id_10, &dma_init_struct_i2s }; +#endif const dma_descr_t dma_SPI_5_RX = { DMA2_Stream3, DMA_REQUEST_SPI5_RX, dma_id_11, &dma_init_struct_spi_i2c }; const dma_descr_t dma_SPI_4_RX = { DMA2_Stream3, DMA_REQUEST_SPI4_RX, dma_id_11, &dma_init_struct_spi_i2c }; const dma_descr_t dma_SPI_5_TX = { DMA2_Stream4, DMA_REQUEST_SPI5_TX, dma_id_12, &dma_init_struct_spi_i2c }; const dma_descr_t dma_SPI_4_TX = { DMA2_Stream4, DMA_REQUEST_SPI4_TX, dma_id_12, &dma_init_struct_spi_i2c }; const dma_descr_t dma_SPI_6_TX = { DMA2_Stream5, BDMA_REQUEST_SPI6_TX, dma_id_13, &dma_init_struct_spi_i2c }; const dma_descr_t dma_SPI_1_TX = { DMA2_Stream5, DMA_REQUEST_SPI1_TX, dma_id_13, &dma_init_struct_spi_i2c }; +#if MICROPY_HW_ENABLE_I2S +const dma_descr_t dma_I2S_1_TX = { DMA2_Stream5, DMA_REQUEST_SPI1_TX, dma_id_13, &dma_init_struct_i2s }; +#endif const dma_descr_t dma_SPI_6_RX = { DMA2_Stream6, BDMA_REQUEST_SPI6_RX, dma_id_14, &dma_init_struct_spi_i2c }; static const uint8_t dma_irqn[NSTREAM] = { diff --git a/ports/stm32/machine_i2s.c b/ports/stm32/machine_i2s.c index 349d07c96c57b..e9dbf906e3e44 100644 --- a/ports/stm32/machine_i2s.c +++ b/ports/stm32/machine_i2s.c @@ -155,12 +155,21 @@ STATIC mp_obj_t machine_i2s_deinit(mp_obj_t self_in); // The frame map is used with the readinto() method to transform the audio sample data coming // from DMA memory (32-bit stereo) to the format specified // in the I2S constructor. e.g. 16-bit mono +#if defined(STM32H7) +STATIC const int8_t i2s_frame_map[NUM_I2S_USER_FORMATS][I2S_RX_FRAME_SIZE_IN_BYTES] = { + { -1, -1, 0, 1, -1, -1, -1, -1 }, // Mono, 16-bits + { 0, 1, 2, 3, -1, -1, -1, -1 }, // Mono, 32-bits + { 0, 1, -1, -1, 2, 3, -1, -1 }, // Stereo, 16-bits + { 0, 1, 2, 3, 4, 5, 6, 7 }, // Stereo, 32-bits +}; +#else STATIC const int8_t i2s_frame_map[NUM_I2S_USER_FORMATS][I2S_RX_FRAME_SIZE_IN_BYTES] = { { 0, 1, -1, -1, -1, -1, -1, -1 }, // Mono, 16-bits { 2, 3, 0, 1, -1, -1, -1, -1 }, // Mono, 32-bits { -1, -1, 0, 1, -1, -1, 2, 3 }, // Stereo, 16-bits { 2, 3, 0, 1, 6, 7, 4, 5 }, // Stereo, 32-bits }; +#endif void machine_i2s_init0() { for (uint8_t i = 0; i < MICROPY_HW_MAX_I2S; i++) { @@ -244,6 +253,7 @@ STATIC size_t ringbuf_available_space(ring_buf_t *rbuf) { // LEFT Channel = 0x99, 0xBB, 0x11, 0x22 // RIGHT Channel = 0x44, 0x55, 0xAB, 0x77 STATIC void reformat_32_bit_samples(int32_t *sample, uint32_t num_samples) { + #if !defined(STM32H7) int16_t sample_ms; int16_t sample_ls; for (uint32_t i = 0; i < num_samples; i++) { @@ -251,6 +261,7 @@ STATIC void reformat_32_bit_samples(int32_t *sample, uint32_t num_samples) { sample_ms = sample[i] >> 16; sample[i] = (sample_ls << 16) + sample_ms; } + #endif } STATIC int8_t get_frame_mapping_index(int8_t bits, format_t format) { @@ -269,14 +280,13 @@ STATIC int8_t get_frame_mapping_index(int8_t bits, format_t format) { } } -STATIC int8_t get_dma_bits(uint16_t mode, int8_t bits) { +STATIC uint32_t get_dma_bits(uint16_t mode, int8_t bits) { if (mode == I2S_MODE_MASTER_TX) { if (bits == 16) { return I2S_DATAFORMAT_16B; } else { return I2S_DATAFORMAT_32B; } - return bits; } else { // Master Rx // always read 32 bit words for I2S e.g. I2S MEMS microphones return I2S_DATAFORMAT_32B; @@ -566,6 +576,21 @@ STATIC bool i2s_init(machine_i2s_obj_t *self) { const pin_af_obj_t *af = pin_find_af(self->sd, AF_FN_I2S, self->i2s_id); GPIO_InitStructure.Alternate = (uint8_t)af->idx; HAL_GPIO_Init(self->sd->gpio, &GPIO_InitStructure); + + #if defined(STM32H7) + // Make sure IOSWP bit is set correctly based on pin and mode + const pin_af_obj_t *pin_af = pin_find_af(self->sd, AF_FN_I2S, self->i2s_id); + if (pin_af != NULL) { + if ((pin_af->type == AF_PIN_TYPE_I2S_SDI + && (self->mode == I2S_MODE_MASTER_RX || self->mode == I2S_MODE_SLAVE_TX)) + || (pin_af->type == AF_PIN_TYPE_I2S_SDO + && (self->mode == I2S_MODE_MASTER_TX || self->mode == I2S_MODE_SLAVE_RX))) { + LL_I2S_DisableIOSwap(self->hi2s.Instance); + } else { + LL_I2S_EnableIOSwap(self->hi2s.Instance); + } + } + #endif } if (HAL_I2S_Init(&self->hi2s) == HAL_OK) { @@ -580,7 +605,9 @@ STATIC bool i2s_init(machine_i2s_obj_t *self) { self->hi2s.hdmatx = &self->hdma_tx; } + #if !defined(STM32H7) __HAL_RCC_PLLI2S_ENABLE(); // start I2S clock + #endif return true; } else { @@ -730,7 +757,12 @@ STATIC void machine_i2s_init_helper(machine_i2s_obj_t *self, size_t n_pos_args, // is SD valid? if (mp_obj_is_type(args[ARG_sd].u_obj, &pin_type)) { pin_af = pin_find_af(MP_OBJ_TO_PTR(args[ARG_sd].u_obj), AF_FN_I2S, self->i2s_id); - if (pin_af->type != AF_PIN_TYPE_I2S_SD) { + if (!(pin_af != NULL && ( + pin_af->type == AF_PIN_TYPE_I2S_SD + #if defined(STM32H7) + || pin_af->type == AF_PIN_TYPE_I2S_SDO || pin_af->type == AF_PIN_TYPE_I2S_SDI + #endif + ))) { mp_raise_ValueError(MP_ERROR_TEXT("invalid SD pin")); } } else { @@ -792,7 +824,9 @@ STATIC void machine_i2s_init_helper(machine_i2s_obj_t *self, size_t n_pos_args, init->MCLKOutput = I2S_MCLKOUTPUT_DISABLE; init->AudioFreq = I2S_AUDIOFREQ_DEFAULT; init->CPOL = I2S_CPOL_LOW; + #if !defined(STM32H7) init->ClockSource = I2S_CLOCK_PLL; + #endif #if defined(STM32F4) init->FullDuplexMode = I2S_FULLDUPLEXMODE_DISABLE; #endif diff --git a/ports/stm32/pin_defs_stm32.h b/ports/stm32/pin_defs_stm32.h index 1f950c1179833..4987f159012ac 100644 --- a/ports/stm32/pin_defs_stm32.h +++ b/ports/stm32/pin_defs_stm32.h @@ -91,6 +91,8 @@ enum { AF_PIN_TYPE_I2S_CK = 0, AF_PIN_TYPE_I2S_MCK, AF_PIN_TYPE_I2S_SD, + AF_PIN_TYPE_I2S_SDO, + AF_PIN_TYPE_I2S_SDI, AF_PIN_TYPE_I2S_WS, AF_PIN_TYPE_I2S_EXTSD, From 6c6f15c04547a198da6345b6ab67b871f2b71d25 Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 25 Mar 2022 18:11:38 +1100 Subject: [PATCH 7/8] stm32/dma: Provide 16 and 32 bit I2S DMA structs. Signed-off-by: Damien George --- ports/stm32/dma.c | 42 +++++++++++++++++++++++++++++++++--------- ports/stm32/dma.h | 26 ++++++++++++++++++++++---- 2 files changed, 55 insertions(+), 13 deletions(-) diff --git a/ports/stm32/dma.c b/ports/stm32/dma.c index d16160f60941d..8f148c66e1c89 100644 --- a/ports/stm32/dma.c +++ b/ports/stm32/dma.c @@ -114,9 +114,10 @@ static const DMA_InitTypeDef dma_init_struct_spi_i2c = { }; #if MICROPY_HW_ENABLE_I2S + // Default parameters to dma_init() for i2s; Channel and Direction // vary depending on the peripheral instance so they get passed separately -static const DMA_InitTypeDef dma_init_struct_i2s = { +static const DMA_InitTypeDef dma_init_struct_i2s_16 = { #if defined(STM32F4) || defined(STM32F7) .Channel = 0, #elif defined(STM32H7) || defined(STM32L0) || defined(STM32L4) @@ -136,6 +137,25 @@ static const DMA_InitTypeDef dma_init_struct_i2s = { .PeriphBurst = DMA_PBURST_SINGLE #endif }; + +#if defined(STM32H7) +// H7 requires different DMA settings for 32-bit transfers. +static const DMA_InitTypeDef dma_init_struct_i2s_32 = { + .Request = 0, + .Direction = DMA_MEMORY_TO_PERIPH, + .PeriphInc = DMA_PINC_DISABLE, + .MemInc = DMA_MINC_ENABLE, + .PeriphDataAlignment = DMA_PDATAALIGN_WORD, + .MemDataAlignment = DMA_MDATAALIGN_WORD, + .Mode = DMA_CIRCULAR, + .Priority = DMA_PRIORITY_LOW, + .FIFOMode = DMA_FIFOMODE_DISABLE, + .FIFOThreshold = DMA_FIFO_THRESHOLD_FULL, + .MemBurst = DMA_MBURST_SINGLE, + .PeriphBurst = DMA_PBURST_SINGLE +}; +#endif + #endif #if ENABLE_SDIO && !defined(STM32H7) @@ -278,8 +298,8 @@ const dma_descr_t dma_I2C_2_RX = { DMA1_Stream2, DMA_CHANNEL_7, dma_id_2, &dma const dma_descr_t dma_SPI_2_RX = { DMA1_Stream3, DMA_CHANNEL_0, dma_id_3, &dma_init_struct_spi_i2c }; const dma_descr_t dma_SPI_2_TX = { DMA1_Stream4, DMA_CHANNEL_0, dma_id_4, &dma_init_struct_spi_i2c }; #if MICROPY_HW_ENABLE_I2S -const dma_descr_t dma_I2S_2_RX = { DMA1_Stream3, DMA_CHANNEL_0, dma_id_3, &dma_init_struct_i2s }; -const dma_descr_t dma_I2S_2_TX = { DMA1_Stream4, DMA_CHANNEL_0, dma_id_4, &dma_init_struct_i2s }; +const dma_descr_t dma_I2S_2_RX_16 = { DMA1_Stream3, DMA_CHANNEL_0, dma_id_3, &dma_init_struct_i2s_16 }; +const dma_descr_t dma_I2S_2_TX_16 = { DMA1_Stream4, DMA_CHANNEL_0, dma_id_4, &dma_init_struct_i2s_16 }; #endif const dma_descr_t dma_I2C_3_TX = { DMA1_Stream4, DMA_CHANNEL_3, dma_id_4, &dma_init_struct_spi_i2c }; #if defined(STM32F7) @@ -306,7 +326,7 @@ const dma_descr_t dma_DCMI_0 = { DMA2_Stream1, DMA_CHANNEL_1, dma_id_9, &dma_in #endif const dma_descr_t dma_SPI_1_RX = { DMA2_Stream2, DMA_CHANNEL_3, dma_id_10, &dma_init_struct_spi_i2c }; #if MICROPY_HW_ENABLE_I2S -const dma_descr_t dma_I2S_1_RX = { DMA2_Stream2, DMA_CHANNEL_3, dma_id_10, &dma_init_struct_i2s }; +const dma_descr_t dma_I2S_1_RX_16 = { DMA2_Stream2, DMA_CHANNEL_3, dma_id_10, &dma_init_struct_i2s_16 }; #endif #if ENABLE_SDIO const dma_descr_t dma_SDIO_0 = { DMA2_Stream3, DMA_CHANNEL_4, dma_id_11, &dma_init_struct_sdio }; @@ -320,7 +340,7 @@ const dma_descr_t dma_SPI_4_TX = { DMA2_Stream4, DMA_CHANNEL_5, dma_id_12, &dma const dma_descr_t dma_SPI_6_TX = { DMA2_Stream5, DMA_CHANNEL_1, dma_id_13, &dma_init_struct_spi_i2c }; const dma_descr_t dma_SPI_1_TX = { DMA2_Stream5, DMA_CHANNEL_3, dma_id_13, &dma_init_struct_spi_i2c }; #if MICROPY_HW_ENABLE_I2S -const dma_descr_t dma_I2S_1_TX = { DMA2_Stream5, DMA_CHANNEL_3, dma_id_13, &dma_init_struct_i2s }; +const dma_descr_t dma_I2S_1_TX_16 = { DMA2_Stream5, DMA_CHANNEL_3, dma_id_13, &dma_init_struct_i2s_16 }; #endif // #if defined(STM32F7) && defined(SDMMC2) && ENABLE_SDIO // const dma_descr_t dma_SDMMC_2 = { DMA2_Stream5, DMA_CHANNEL_11, dma_id_13, &dma_init_struct_sdio }; @@ -613,8 +633,10 @@ const dma_descr_t dma_I2C_2_RX = { DMA1_Stream2, DMA_REQUEST_I2C2_RX, dma_id_2, const dma_descr_t dma_SPI_2_RX = { DMA1_Stream3, DMA_REQUEST_SPI2_RX, dma_id_3, &dma_init_struct_spi_i2c }; const dma_descr_t dma_SPI_2_TX = { DMA1_Stream4, DMA_REQUEST_SPI2_TX, dma_id_4, &dma_init_struct_spi_i2c }; #if MICROPY_HW_ENABLE_I2S -const dma_descr_t dma_I2S_2_RX = { DMA1_Stream3, DMA_REQUEST_SPI2_RX, dma_id_3, &dma_init_struct_i2s }; -const dma_descr_t dma_I2S_2_TX = { DMA1_Stream4, DMA_REQUEST_SPI2_TX, dma_id_4, &dma_init_struct_i2s }; +const dma_descr_t dma_I2S_2_RX_16 = { DMA1_Stream3, DMA_REQUEST_SPI2_RX, dma_id_3, &dma_init_struct_i2s_16 }; +const dma_descr_t dma_I2S_2_RX_32 = { DMA1_Stream3, DMA_REQUEST_SPI2_RX, dma_id_3, &dma_init_struct_i2s_32 }; +const dma_descr_t dma_I2S_2_TX_16 = { DMA1_Stream4, DMA_REQUEST_SPI2_TX, dma_id_4, &dma_init_struct_i2s_16 }; +const dma_descr_t dma_I2S_2_TX_32 = { DMA1_Stream4, DMA_REQUEST_SPI2_TX, dma_id_4, &dma_init_struct_i2s_32 }; #endif const dma_descr_t dma_I2C_3_TX = { DMA1_Stream4, DMA_REQUEST_I2C3_TX, dma_id_4, &dma_init_struct_spi_i2c }; const dma_descr_t dma_I2C_4_TX = { DMA1_Stream5, BDMA_REQUEST_I2C4_TX, dma_id_5, &dma_init_struct_spi_i2c }; @@ -632,7 +654,8 @@ const dma_descr_t dma_DCMI_0 = { DMA2_Stream1, DMA_REQUEST_DCMI, dma_id_9, &dma #endif const dma_descr_t dma_SPI_1_RX = { DMA2_Stream2, DMA_REQUEST_SPI1_RX, dma_id_10, &dma_init_struct_spi_i2c }; #if MICROPY_HW_ENABLE_I2S -const dma_descr_t dma_I2S_1_RX = { DMA2_Stream2, DMA_REQUEST_SPI1_RX, dma_id_10, &dma_init_struct_i2s }; +const dma_descr_t dma_I2S_1_RX_16 = { DMA2_Stream2, DMA_REQUEST_SPI1_RX, dma_id_10, &dma_init_struct_i2s_16 }; +const dma_descr_t dma_I2S_1_RX_32 = { DMA2_Stream2, DMA_REQUEST_SPI1_RX, dma_id_10, &dma_init_struct_i2s_32 }; #endif const dma_descr_t dma_SPI_5_RX = { DMA2_Stream3, DMA_REQUEST_SPI5_RX, dma_id_11, &dma_init_struct_spi_i2c }; const dma_descr_t dma_SPI_4_RX = { DMA2_Stream3, DMA_REQUEST_SPI4_RX, dma_id_11, &dma_init_struct_spi_i2c }; @@ -641,7 +664,8 @@ const dma_descr_t dma_SPI_4_TX = { DMA2_Stream4, DMA_REQUEST_SPI4_TX, dma_id_12, const dma_descr_t dma_SPI_6_TX = { DMA2_Stream5, BDMA_REQUEST_SPI6_TX, dma_id_13, &dma_init_struct_spi_i2c }; const dma_descr_t dma_SPI_1_TX = { DMA2_Stream5, DMA_REQUEST_SPI1_TX, dma_id_13, &dma_init_struct_spi_i2c }; #if MICROPY_HW_ENABLE_I2S -const dma_descr_t dma_I2S_1_TX = { DMA2_Stream5, DMA_REQUEST_SPI1_TX, dma_id_13, &dma_init_struct_i2s }; +const dma_descr_t dma_I2S_1_TX_16 = { DMA2_Stream5, DMA_REQUEST_SPI1_TX, dma_id_13, &dma_init_struct_i2s_16 }; +const dma_descr_t dma_I2S_1_TX_32 = { DMA2_Stream5, DMA_REQUEST_SPI1_TX, dma_id_13, &dma_init_struct_i2s_32 }; #endif const dma_descr_t dma_SPI_6_RX = { DMA2_Stream6, BDMA_REQUEST_SPI6_RX, dma_id_14, &dma_init_struct_spi_i2c }; diff --git a/ports/stm32/dma.h b/ports/stm32/dma.h index 9b0b4c77a6621..7411586699ac9 100644 --- a/ports/stm32/dma.h +++ b/ports/stm32/dma.h @@ -57,10 +57,28 @@ extern const dma_descr_t dma_SDMMC_2; extern const dma_descr_t dma_SPI_6_RX; extern const dma_descr_t dma_SDIO_0; extern const dma_descr_t dma_DCMI_0; -extern const dma_descr_t dma_I2S_1_RX; -extern const dma_descr_t dma_I2S_1_TX; -extern const dma_descr_t dma_I2S_2_RX; -extern const dma_descr_t dma_I2S_2_TX; + +#if defined(STM32H7) +// H7 requires different DMA settings for 16-bit transfers. +extern const dma_descr_t dma_I2S_1_RX_16; +extern const dma_descr_t dma_I2S_1_RX_32; +extern const dma_descr_t dma_I2S_1_TX_16; +extern const dma_descr_t dma_I2S_1_TX_32; +extern const dma_descr_t dma_I2S_2_RX_16; +extern const dma_descr_t dma_I2S_2_RX_32; +extern const dma_descr_t dma_I2S_2_TX_16; +extern const dma_descr_t dma_I2S_2_TX_32; +#else +// F4/F7 uses the same DMA settings for 16-bit and 32-bit transfers. +extern const dma_descr_t dma_I2S_1_RX_16; +#define dma_I2S_1_RX_32 dma_I2S_1_RX_16 +extern const dma_descr_t dma_I2S_1_TX_16; +#define dma_I2S_1_TX_32 dma_I2S_1_TX_16 +extern const dma_descr_t dma_I2S_2_RX_16; +#define dma_I2S_2_RX_32 dma_I2S_2_RX_16 +extern const dma_descr_t dma_I2S_2_TX_16; +#define dma_I2S_2_TX_32 dma_I2S_2_TX_16 +#endif #elif defined(STM32G4) From 9c9a930a58e9ad90287c86ab49bdb71b0a355600 Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 8 Feb 2022 18:17:14 +1100 Subject: [PATCH 8/8] stm32/machine_i2s: Correctly set the DMA transfer size. Signed-off-by: Damien George --- ports/stm32/machine_i2s.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/ports/stm32/machine_i2s.c b/ports/stm32/machine_i2s.c index e9dbf906e3e44..a8d50ec88a223 100644 --- a/ports/stm32/machine_i2s.c +++ b/ports/stm32/machine_i2s.c @@ -537,18 +537,26 @@ STATIC bool i2s_init(machine_i2s_obj_t *self) { __SPI1_CLK_ENABLE(); // configure DMA streams if (self->mode == I2S_MODE_MASTER_RX || self->mode == I2S_MODE_SLAVE_RX) { - self->dma_descr_rx = &dma_I2S_1_RX; + self->dma_descr_rx = &dma_I2S_1_RX_32; // always 32-bit } else { - self->dma_descr_tx = &dma_I2S_1_TX; + if (self->hi2s.Init.DataFormat == I2S_DATAFORMAT_16B) { + self->dma_descr_tx = &dma_I2S_1_TX_16; + } else { + self->dma_descr_tx = &dma_I2S_1_TX_32; + } } } else if (self->i2s_id == 2) { self->hi2s.Instance = I2S2; __SPI2_CLK_ENABLE(); // configure DMA streams if (self->mode == I2S_MODE_MASTER_RX || self->mode == I2S_MODE_SLAVE_RX) { - self->dma_descr_rx = &dma_I2S_2_RX; + self->dma_descr_rx = &dma_I2S_2_RX_32; // always 32-bit } else { - self->dma_descr_tx = &dma_I2S_2_TX; + if (self->hi2s.Init.DataFormat == I2S_DATAFORMAT_16B) { + self->dma_descr_tx = &dma_I2S_1_TX_16; + } else { + self->dma_descr_tx = &dma_I2S_2_TX_32; + } } } else { // invalid id number; should not get here as i2s object should not pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy