Skip to content

Second I2S on ESP32 non-working #7111

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
1 task done
musteresel opened this issue Aug 10, 2022 · 7 comments
Closed
1 task done

Second I2S on ESP32 non-working #7111

musteresel opened this issue Aug 10, 2022 · 7 comments
Assignees
Labels
Area: Peripherals API Relates to peripheral's APIs. Status: Awaiting triage Issue is waiting for triage
Milestone

Comments

@musteresel
Copy link

Board

ESP32 NodeMCU

Device Description

(irrelevant for issue)

Hardware Configuration

(irrelevant for issue)

Version

v2.0.4

IDE Name

Arduino IDE

Operating System

Windows 10

Flash frequency

80MHz

PSRAM enabled

no

Upload speed

921600

Description

When going to this part of the code

while(ESP_OK != esp_i2s::i2s_driver_install((esp_i2s::i2s_port_t) _deviceIndex, &i2s_config, _I2S_EVENT_QUEUE_LENGTH, &_i2sEventQueue)){

then it causes the value of _bitsPerSample to change to 0.

This later causes this assertion to fail:
https://github.com/espressif/esp-idf/blob/1b16ef6cfc2479a08136782f9dc57effefa86f66/components/esp_ringbuf/ringbuf.c#L874
That part of the code is called from here:

_buffer_byte_size = _i2s_dma_buffer_size * (_bitsPerSample / 8) * _I2S_DMA_BUFFER_COUNT * 2;
_input_ring_buffer = xRingbufferCreate(_buffer_byte_size, RINGBUF_TYPE_BYTEBUF);

I attached a debugger (Segger J-Link via steps defined here, basically using USBDriverTool to change J-Link driver to WinUSB, then using openocd -f interface/jlink.cfg -c "adapter_khz 1000" -f board/esp-wroom-32.cfg, then connecting using gdb supplied in esp-idf 4.4.2) to get to the root of this, and got so far as to find out that the actual change seems to happen in this function:
https://github.com/espressif/esp-idf/blob/1b16ef6cfc2479a08136782f9dc57effefa86f66/components/hal/esp32/include/hal/i2s_ll.h#L920-L930

(gdb) p/x &_bitsPerSample
$2 = 0x3ffc14f4 
(gdb) watch *0x3ffc14f4
Hardware watchpoint 2: *0x3ffc14f4
(gdb) display *((int32_t *)0x3ffc14f4)
3: *((int32_t *)0x3ffc14f4) = 24 
(gdb) c
Thread 1 received signal SIGTRAP, Trace/breakpoint trap.
0x400de3b0 in i2s_ll_enable_builtin_adc (enable=false, hw=<optimized out>) at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/hal/esp32/include/hal/i2s_ll.h:929
929     /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/hal/esp32/include/hal/i2s_ll.h: No such file or directory.
3: *((int32_t *)0x3ffc14f4) = 24
(gdb) s
i2s_hal_config_param (hal=0x3ffb9998, hal_cfg=0x3ffb99a4) at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/hal/i2s_hal.c:299
299     /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/hal/i2s_hal.c: No such file or directory.
3: *((int32_t *)0x3ffc14f4) = 0

(this shows L929 as offender, but that's strange to me, setting to 0 seems incorrect for this? https://github.com/espressif/esp-idf/blob/1b16ef6cfc2479a08136782f9dc57effefa86f66/components/hal/esp32/include/hal/i2s_ll.h#L929)

Sketch

~~~c++
#include <I2S.h>

I2SClass I2S1(1 /*I2S1*/, 0 /*as in I2S.c*/, PIN_I2S1_SD, PIN_I2S1_SCK, PIN_I2S1_FS); // global variable

// in setup
I2S1.begin(I2S_PHILIPS_MODE, 16000, 24);
~~~

Debug Message

(None, Hard Reset)

Other Steps to Reproduce

No response

I have checked existing issues, online documentation and the Troubleshooting Guide

  • I confirm I have checked existing issues, online documentation and Troubleshooting guide.
@musteresel musteresel added the Status: Awaiting triage Issue is waiting for triage label Aug 10, 2022
@musteresel
Copy link
Author

musteresel commented Aug 10, 2022

edit: The parameters of the function call only become valid after stepping once into the function, so what we see here is a GDB usage error on my side

Adding to this, I just looked up how the call stack looks like when I2S (the "default" one on I2S0) has its begin called, breaking at xRingbufferCreate where the assertion with the other instance fails.

Backtrace:

(gdb) br xRingbufferCreate
Breakpoint 2 at 0x40087b60: file /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/esp_ringbuf/ringbuf.c, line 873. 
(gdb) c
Continuing.
Thread 3 hit Breakpoint 2, xRingbufferCreate (xBufferSize=1073485104, xBufferType=RINGBUF_TYPE_ALLOWSPLIT)
    at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/esp_ringbuf/ringbuf.c:873 
873     /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/esp_ringbuf/ringbuf.c: No such file or directory.
(gdb) bt
#0  xRingbufferCreate (xBufferSize=1073485104, xBufferType=RINGBUF_TYPE_ALLOWSPLIT) at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/esp_ringbuf/ringbuf.c:873
#1  0x400d2adc in I2SClass::begin (this=0x3ffc1530 <I2S>, mode=<optimized out>, sampleRate=<optimized out>, bitsPerSample=24, driveClock=true)
    at C:\Users\djour\Documents\ArduinoData\packages\esp32\hardware\esp32\2.0.4\libraries\I2S\src\I2S.cpp:298 
#2  0x400d2ba3 in I2SClass::begin (this=0x3ffc1530 <I2S>, mode=0, sampleRate=16000, bitsPerSample=24) at C:\Users\djour\Documents\ArduinoData\packages\esp32\hardware\esp32\2.0.4\libraries\I2S\src\I2S.cpp:226 
#3  0x400d15ff in setup () at C:\Users\djour\Documents\Arduino\esp32-test/esp32-test.ino:23
#4  0x400d3ee9 in loopTask (pvParameters=0x0) at C:\Users\djour\Documents\ArduinoData\packages\esp32\hardware\esp32\2.0.4\cores\esp32\main.cpp:42
(gdb) frame 1
#1  0x400d2adc in I2SClass::begin (this=0x3ffc1530 <I2S>, mode=<optimized out>, sampleRate=<optimized out>, bitsPerSample=24, driveClock=true)
    at C:\Users\djour\Documents\ArduinoData\packages\esp32\hardware\esp32\2.0.4\libraries\I2S\src\I2S.cpp:298 
298       _input_ring_buffer  = xRingbufferCreate(_buffer_byte_size, RINGBUF_TYPE_BYTEBUF); 
(gdb) p _bitsPerSample
$1 = 24
(gdb) p _buffer_byte_size
$2 = 1536 
(gdb) p RINGBUF_TYPE_BYTEBUF == RINGBUF_TYPE_ALLOWSPLIT
$4 = false

What I find strange is that there's the call xRingbufferCreate (xBufferSize=1073485104, xBufferType=RINGBUF_TYPE_ALLOWSPLIT) ... but (first parameter) _buffer_byte_size == 1536 and the second parameter also does not match with what we see in the source (at tag 2.0.4):

_input_ring_buffer = xRingbufferCreate(_buffer_byte_size, RINGBUF_TYPE_BYTEBUF);

To me this looks like a garbled stack.

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200 /*500000*/);

  Serial.println("BR 1");
  while (!Serial.available()); Serial.read(); // ========== attached the debugger while waiting here
  i2s_mode_t const m = I2S_PHILIPS_MODE;
  uint32_t const sr = 16000;
  uint8_t const bps = 24;
  if (!I2S.begin(m, sr, bps)) { // ================== Here is where the debugger backtrace from this comment is from
    Serial.println("[E] Failed to init I2S!");
    while (1);
  }
  Serial.println("BR 2");
  while (!Serial.available()); Serial.read();
  I2S1.setBufferSize(128);
  if (!I2S1.begin(m, sr, bps)) {
    Serial.println("[E] Failed to init I2S1");
    while (1);
  }
  Serial.println("STOP"); while(1);
}

@musteresel
Copy link
Author

From the linker map:

0x3ffc2098                _heap_start = ABSOLUTE (.)
0x40000000                _heap_end = 0x40000000

From a backtrack:

#2  0x400de4e0 in i2s_hal_config_param (hal=0x3ffb9998, hal_cfg=0x3ffb99a4) at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/hal/i2s_hal.c:320

Note that hal=0x3ffb9998 is outside of the heap!

But ...
https://github.com/espressif/esp-idf/blob/1b16ef6cfc2479a08136782f9dc57effefa86f66/components/driver/i2s.c#L1972

i2s_hal_config_param(&(pre_alloc_i2s_obj->hal), &pre_alloc_i2s_obj->hal_cfg);

... and ...

i2s_obj_t *pre_alloc_i2s_obj = calloc(1, sizeof(i2s_obj_t));

... therefore pre_alloc_i2s_obj and its member hal are heap allocated, but outside of the heap memory region.

But they're inside ...

0x3ffc2098                _static_data_end = _bss_end
0x3ffc14c8                I2S1

the data section ...

@musteresel
Copy link
Author

Short note ... renaming I2SClass I2S1 to I2SClass I2S1_ to avoid (potentially?) wrong linkage (with I2S1 being the actual hardware; memory mapped) surprisingly helps; setting up the second I2S this way "works" .. but the input queue never fills, meaning the DMA tx done is never called. No idea why.
Not using I2S0 at the same time doesn't help, either.

@VojtechBartoska VojtechBartoska added the Area: Peripherals API Relates to peripheral's APIs. label Aug 11, 2022
@PilnyTomas
Copy link
Contributor

PilnyTomas commented Aug 12, 2022

I think I might have a lead:
I2S._onTransferComplete();
I will fix that as soon as possible.
But that solves only 2nd half of the problem - still getting bitsPerSample == 0 after calling i2s_driver_install - this one seems more like IDF bug.

@musteresel
Copy link
Author

Ah yes, that makes sense as to why the input queue doesn't fill.

Did you have the issue with bitsPerSample being written from within IDF code also after renaming (or not using the name) I2S1 (which is the same name as the peripheral) ? I honestly did not check this, but assumed that fixed it (because I then got past the assertion mentioned above).

@PilnyTomas
Copy link
Contributor

No, different name seems to work.

@PilnyTomas
Copy link
Contributor

Please try out the changes in the mentioned PR #7117 I have renamed the second I2S to I2S_1
The PR will be merged after testing.

Repository owner moved this from In Progress to Done in Arduino ESP32 Core Project Roadmap Nov 9, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area: Peripherals API Relates to peripheral's APIs. Status: Awaiting triage Issue is waiting for triage
Projects
Development

No branches or pull requests

3 participants