PSoC 6 HAL I2S circular buffer implementation with DMA freeRTOS

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
lock attach
Attachments are accessible only for community members.
ArMu_4673571
Employee
Employee
5 replies posted First question asked First reply posted

Dear all,

I'm trying to make an implementation of a circular buffer with the I2S peripheral to read some data with the RX lines, processing it, and then write it on the TX line. I'm using freeRTOS and currently have two tasks. On the first one I'm making the basic app configuration and in the second one "audio_stream.c" I'm making the implementation of the circular buffer. This implementation is based on the I2S example of the HAL library (snippet 3 and 4). But for some reason I can't get it working. What I've verified until now is:

- I2S clocks are correctly configured and initialized (verified with a scope)

- I2S block can initialize properly (init function returning success)

- The system is correctly entering in the audio stream task (verified with debugging) and (on purpose) remains there.

- We have data coming to the RX line.

- MCU used is CY8C62ABZI-S2D44

- If line 85 is used (cyhal_i2s_set_async_mode) TX remains always low. If commented (not used) is transmitting data but apparently it is just noise (verified with audio precision i2s receiver, we are also verifying the RX data line and seems ok, trying a sine wave).

Could you please help checking the implementation?

Best regards,

Ariel

0 Likes
1 Solution
lock attach
Attachments are accessible only for community members.

Hi Ariel,

I created a simple project based on the PDM to I2S project that implements a ping-pong buffer. I modified to use I2S RX instead of PDM. It also streams in real time what ever you read from I2S RX to I2S TX. Just press the kit's button to start streaming. I tested using CY8CKIT-062-WIFI-BT + TFT shield.

View solution in original post

0 Likes
10 Replies
RodolfoGL
Employee
Employee
250 solutions authored 250 sign-ins 5 comments on KBA

Hi Ariel,

Have you enabled the CYHAL_I2S_ASYNC_TX_COMPLETE event using these functions:

cyhal_i2s_register_callback(&i2s, i2s_isr_handler, NULL);

cyhal_i2s_enable_event(&i2s, CYHAL_I2S_ASYNC_RX_COMPLETE, CYHAL_ISR_PRIORITY_DEFAULT, true);

You need to implement the i2s_isr_handler to notify the RTOS that the event occurred, then you can call the next async transfer. There is no need to have this IF condition:

if(0 != CYHAL_I2S_ASYNC_RX_COMPLETE)

This is a MACRO, not a register, so it will be always true.

0 Likes

Hi Rodolfo,

Thank you for your quick reply.  From the library documentation I understood that if you use DMA for the I2S you don't need to use an ISR. But looking again now at the example of the HAL library (Snippet 3) it is using both:

cy_rslt_t result = cyhal_i2s_set_async_mode(&i2s, CYHAL_ASYNC_DMA, CYHAL_DMA_PRIORITY_DEFAULT);

cyhal_i2s_register_callback(&i2s, &i2s_event_handler_transmit_streaming, &i2s);

so my remainign questions would be:

- Eventhoiugh the example is using ISR , if I use the set asyn mode to DMA the CPU won't be "charged" with this task? (/* Configure asynchronous transfers to use DMA to free up the CPU during transfers */)

- If I implement for example the snippet 4 , appart fro processing the data on the full buffer then I need to write the data to the TX FIFO. Where should I put the cyhal_i2s_write_async ? on the same ISR handler or shoiuld i create and register another handler to write?

Best regards,

Ariel

0 Likes
lock attach
Attachments are accessible only for community members.

Hi Again,

So I recoded everything without freeRTOS and it seems that the problem is that the i2s ISR handler is never being called. In this my hanlder function is "i2s_event_handler_stream". I'm veryfing that just by turning on or off a gpio inside the handler. Could you please check if there is anything I'm not setting up? Right now everything is following the i2s hal streaming example.

Best regards,

Ariel

0 Likes

Ariel,

Few comments:

1) It is nice to check the return of the functions to verify if they were executed successfully. If they are not, you can enter in a while loop and blink an LED, so you know a problem occurred (including the init functions).

2) You can't keep registering the event and set_async_mode in every interaction of the while loop. Only do once outside the while loop. Here is the flow:

a) Register the ASYNC_COMPLETE callback event and set sync mode.

b) Call async_read()

c) Enter in the while loop

   c.1) Check a flag set by the callback you registered on ASYNC_COMPLETE

      c.1.1) If true, clear the flag

      c.1.2) Call the next async_read().

   c.2) If false, you can go to sleep or do other things.

As a note, there is no difference between using DMA or CPU in terms of functionality. Actually at the moment, the DMA implementation is not optimal. It is not leveraging the hardware triggers, so there is an interrupt going on background in both cases - DMA and CPU.

So you don't need to use DMA now. Even if you do, the firmware flow will be exactly the same.

A good example to refer is this one. The flow is the exactly the same if you want to read from I2S.

GitHub - cypresssemiconductorco/mtb-example-psoc6-i2s: This example demonstrates how to use the I2S ...

0 Likes

Hi Rodolfo,

Did all that but for some reason the event triggered by ASYNC_COMPLETE is never been triggered. It's working perfectly fine with write_async , but not with read_async.

All is been initiated successfully and all the functions that can be checked are returning CY_RSLT_SUCCESS.

is that function tested? I haven't seen any examples with RX actually.

Best regards,

Ariel

0 Likes

Hi Ariel,

Which hardware are you using to test this?

Yes, the I2S RX APIs were tested. We have this code example working:

GitHub - cypresssemiconductorco/mtb-example-psoc6-usb-audio-device-freertos: This example demonstrat...

0 Likes

Hi Rodolfo,

We are using our own board with CY8C624ABZI-S2D44.

hardware has been verified doing simple samples by samples throughput with lower level PDL library from RX to TX and worked perfectly fine.

We are using TX as master.

Best,

Ariel

0 Likes

Can you share the schematic here? If not, you can send an email directly to me.

I guess you configured the RX as a slave, which means you have to configure the WS and SCL pins as inputs. The HAL library will do that automatically for you, but you need to make sure these signals are being driven by your hardware.

0 Likes

Already verified that we have all the clock lines up and running.

which email should we send the schematics?

Best,

Ariel

0 Likes
lock attach
Attachments are accessible only for community members.

Hi Ariel,

I created a simple project based on the PDM to I2S project that implements a ping-pong buffer. I modified to use I2S RX instead of PDM. It also streams in real time what ever you read from I2S RX to I2S TX. Just press the kit's button to start streaming. I tested using CY8CKIT-062-WIFI-BT + TFT shield.

0 Likes