nRF52840 I2S write failed -11

Hello,

I am using two nrf52840 DKs to test ble transmission and i2s output. The nRF Connect SDK I use is v2.6.0.

Both of them are ble connected. One sends data to the other through ble, and the other receives the data and outputs it to i2s.

The i2s is set to write data every 100ms.

During the test, I found that every time i2s writes 100ms of data, it must do an I2S_TRIGGER_STOP, otherwise an error will occur.

Just like the code below, I must first do I2S_TRIGGER_START in each round, then write data to i2s tx, and finally I must do I2S_TRIGGER_STOP.

void i2s_send(void){
	int ret;
	memset(mem_block, 0, BLOCK_SIZE);
	ret = i2s_write(i2s_dev_tx, mem_block, BLOCK_SIZE);
	if (ret < 0) {
		LOG_ERR("Failed to write block %d", ret);
	}
	/* Put data into the tx buffer */
	for (int i = 0; i < 9600; i++) {
		((int16_t*)mem_block)[i] = (int16_t)data_buf_modify[i];
  	}
	ret = i2s_trigger(i2s_dev_tx, I2S_DIR_TX, I2S_TRIGGER_START);
	if (ret < 0) {
		LOG_ERR("Failed to trigger command I2S_TRIGGER_START on TX: %d\n", ret);
	}
	ret = i2s_write(i2s_dev_tx, mem_block, BLOCK_SIZE);
	if (ret < 0) {
		LOG_ERR("Failed to write data: %d", ret);
	}else{
		LOG_INF("Success to write data.");
	}
	ret = i2s_trigger(i2s_dev_tx, I2S_DIR_TX, I2S_TRIGGER_STOP);
	if (ret < 0) {
		LOG_ERR("Failed to trigger command I2S_TRIGGER_DRAIN on TX: %d\n", ret);
	}
}

This causes my i2s output to be noisy, which I think is due to the pause during playback.

But if I only do I2S_TRIGGER_START at the beginning, and then do not do I2S_TRIGGER_STOP after i2s write, but directly do the next round of i2s write, I will get the following error:

[00:00:00.395,660] <inf> central_test: Success to write data.
[00:00:00.395,660] <inf> central_test: Success to write data.
[00:00:00.396,026] <inf> central_test: Success to write data.
[00:00:00.396,057] <inf> central_test: Success to write data.
[00:00:00.496,856] <inf> central_test: Success to write data.
[00:00:01.496,948] <err> central_test: Failed to write data: -11
[00:00:02.497,100] <err> central_test: Failed to write data: -11
[00:00:03.497,253] <err> central_test: Failed to write data: -11
[00:00:04.497,375] <err> central_test: Failed to write data: -11

I encountered a similar problem in this post, and it has solved by replacing i2s_write with i2s_buf_write.

But after joining ble communication, I encountered the same problem and used the same solution to no avail.

I'm confused as to why there is this difference. Is it because nrf52840 cannot continuously do i2s write while receiving ble data? Is it necessary to stop i2s first and then start to write continuously?

  • Thank you for your assistance.

    I added debug at the end of i2s_nrfx_write to output the state after successful writing.

    [00:00:38.656,372] <inf> i2s_nrfx: After Write state: 1
    [00:00:38.657,501] <inf> i2s_nrfx: After Write state: 2

    It seems that the state after successful writing is I2S_STATE_RUNNING, but the next write will change to I2S_STATE_ERROR.

    I don't know what happened to cause this state to change.

    In this post where I've asked the question, this problem does not occur. The difference between them is that this post uses i2s to play the same pcm data, so mem_block only needs to be written once and does not need to be changed subsequently. My current case is that mem_block needs to be changed every time before writing to i2s. Could this problem be caused by changes in mem_block?

    Let me restate my problem. As I said at the beginning, if I use i2s_write and add i2s_trigger (i2s_dev_tx, I2S_DIR_TX, I2S_TRIGGER_STOP) after each successful write, there will be no errors and continuous writes will be successful, but the sound will be intermittent.

    In fact, what I want to solve is the intermittent problem caused by I2S_TRIGGER_STOP, but removing I2S_TRIGGER_STOP will cause these problems. Is there any other way to solve this intermittent problem?

  • It looks like the BLE throughput and buffer handling are not fast enough to provide continuous playback of your audio. The app must be able to keep the i2s buffers filled for uninterrupted playback and the error you got below indicates that this is not the case.

    [00:00:25.560,302] <err> i2s_nrfx: Next buffers not supplied on time

    You should be able to use I2S_TRIGGER_PREPARE command to recover from this error state. However, it will still lead to interrupts in your playback.

    Have you tried filling up your TX i2s queue by calling i2s_buf_write() multiple times before issuing the I2S_TRIGGER_START command? 

    Also, I would recommend evaluating LE audio (https://docs.nordicsemi.com/bundle/ncs-latest/page/nrf/applications/nrf5340_audio/index.html) if your application requires streaming of audio. Regular BLE may be suitable if you only need to receive short audio sequences.

Related