← index #14050Issue #16076
Related · high · value 0.112
QUERY · ISSUE

Bug - I2S communication disrupted by arbitrary function call following I2C initialization.

openby jimmoopened 2024-03-07updated 2024-03-16

Discussed in https://github.com/orgs/micropython/discussions/14009

<div type='discussions-op-text'>

<sup>Originally posted by ajbradburn March 3, 2024</sup>
Bug - I2S communication disrupted by arbitrary function call following I2C initialization.

I have discovered that I2S communication is somehow disrupted by initializing I2C, and then calling any function.

A work-around is to do something as simple a call ‘print’ after the arbitrary function call.

Here is an example of a script that demonstrates the bug:


from machine import I2C, Pin, I2S

def emptyFunction():
    return

i2c = I2C(0, scl=3, sda=8)
ser = emptyFunction()
print('Safety Print') # CRITICALLY IMPORTANT. This print statement enables I2S to work properly. Some combination of the i2c assignment, and then a function call afterwards makes the I2S sound terrible. Simply printing something resolves the issue… Comment this print call to experience bug.

bclk = Pin(5) # Clock Pin
lrc = Pin(6) # Channel Select Pin
din = Pin(4) # Data Pin

audio_out = I2S(
    1, 
    sck=bclk, ws=lrc, sd=din, 
    mode=I2S.TX,
    bits=16,
    format=I2S.MONO, 
    rate=44100,
    ibuf=1024
    )

def playAudio(file):
    print(file)
    if True:
        wav_file = file
        wav = open(wav_file,'rb')
        pos = wav.seek(44) 

        wav_samples = bytearray(1024)
        wav_samples_mv = memoryview(wav_samples)
        audio_out.shift

        while True:
            num_read = wav.readinto(wav_samples_mv)
            if num_read == 0:
                break
            num_written = 0
            # Increase the volume.
            #I2S.shift(buf=wav_samples_mv, bits=16, shift=1)
            while num_written < num_read:
                num_written += audio_out.write(wav_samples_mv[num_written:num_read])
        wav.close()

playAudio('snake.wav')

audio_out.deinit()

I have tested this with blocking, and non blocking I2S implementation with the same result.

I discovered this while trying to operate a PCA9685 and a Max98357 on an ESP32-S3-WROOM-1 using Micropython v1.22.2 (2024-02-22).

Files can be found here:
https://github.com/ajbradburn/ESP32-PuppetRemote/blob/main/code/sound_test.py
https://github.com/ajbradburn/ESP32-PuppetRemote/blob/main/code/sound_test2.py
https://github.com/ajbradburn/ESP32-PuppetRemote/blob/main/code/snake.wav</div>

CANDIDATE · ISSUE

i2s bug?

openby shaojiajun314opened 2024-10-25updated 2026-03-24
bugport-esp32

Port, board and/or hardware

esp32

MicroPython version

E (151878) i2s_common: i2s_alloc_dma_desc(417): allocate DMA buffer failed
E (151878) i2s_std: i2s_std_set_slot(103): allocate memory for dma descriptor failed
E (151878) i2s_std: i2s_channel_init_std_mode(217): initialize channel failed while setting slot
E (151888) i2s_common: i2s_channel_enable(966): the channel has already enabled or not initialized

image

Reproduction

def _play_i2s_dac(self, name):
	if self.is_play:
		return False
	self.is_play = True
	if isinstance(name, str):
		name = self.buildpath(name)
	with wav_open(name) as f:
		total = f.getnframes()
		# print('total: ', total)
		print('rate: ', f.getframerate())
		try:
			i2s = I2S(
				0,
				# sck=Pin(14), ws=Pin(13), sd=Pin(12),
				sck=Pin(CONF['i2sBCLK']),
				ws=Pin(CONF['i2sLRC']),
				sd=Pin(CONF['i2sDIN']),
				mode=I2S.TX,
				bits=16,
				format=I2S.MONO,
				rate=f.getframerate(),
				ibuf=1024
			)
		except Exception as e:
			print('''

E (35978) i2s_common: i2s_alloc_dma_desc(417): allocate DMA buffer failed
E (35978) i2s_std: i2s_std_set_slot(103): allocate memory for dma descriptor failed
E (35988) i2s_std: i2s_channel_init_std_mode(217): initialize channel failed while setting slot
E (35998) i2s_common: i2s_channel_enable(966): the channel has already enabled or not initialized
?''')
print(e)
self.is_play = False
return False
while 1:
read_size = min(total, self.buffer_size)
tmp = f.readframes(read_size)
tmp = bytearray(tmp)
I2S.shift(buf=tmp, bits=16, shift=self.dB)
i2s.write(tmp)
total -= read_size
if total <= 0:
break
i2s.deinit()
self.is_play = False
return True

Expected behaviour

No response

Observed behaviour

E (151878) i2s_common: i2s_alloc_dma_desc(417): allocate DMA buffer failed
E (151878) i2s_std: i2s_std_set_slot(103): allocate memory for dma descriptor failed
E (151878) i2s_std: i2s_channel_init_std_mode(217): initialize channel failed while setting slot
E (151888) i2s_common: i2s_channel_enable(966): the channel has already enabled or not initialized

Additional Information

No, I've provided everything above.

Code of Conduct

Yes, I agree

Keyboard

j / / n
next pair
k / / p
previous pair
1 / / h
show query pane
2 / / l
show candidate pane
c
copy suggested comment
r
toggle reasoning
g i
go to index
?
show this help
esc
close overlays

press ? or esc to close

copied