Hi,
I'm trying to use Emios PWM (OPWMB mode) and feed them with DMA. I have set up a test application that has two DMA buffers configured in scatter gather mode. When the first one is finished playing, the second one is being played. Right now, I don't update the buffers but in the final application, while a buffer is being played, the other one will get updated and buffers will be played in loop.
I'm using S32 Design Studio 3.5 and S32K3XX Real-Time Drivers AUTOSAR R21-11 Version 5.0.0.
I've set up the DMA channel 0 in scatter gather mode with 2 elements (2 buffers of 128 elements each). The source is a buffer of int16 therefore the "source signed offset" is set to 2 and "transfer size" is also set to 2. The destination is an Emios register (IP_EMIOS_0->CH.UC[1].B) therefore, the "destination signed offset" is set to 0 and "transfer size" is set to 2. Since the source buffers have 128 elements, the "source last address adjustment" is set to -256 (128 * sizeof(int16)).
The PWM is set to trigger a DMA request (Flag Event response -> EMIOS_PWM_IP_DMA_REQUEST).
I've attached my test application which runs on a S32K312EVB-Q172 board. Right now, the buffers don't play in a loop, they should be played only once but they are not being played at all. I check with an oscilloscope and I don't see the PWM duty cycle changing
My question is how to configure the DMAMUX to link Emios PWM with DMA channel 0? I don't see where I can configure this. Is it even possible what I'm trying to do? If not, do you have another solution to propose?
Thanks for your help!
Hugo
Solved! Go to Solution.
Hi Senlent,
After some tests, I figured that the ISR is called only when both buffers are played (every ~8.72 ms) on my side unlike on your oscilloscope screenshot. It seems normal to me because the "Enable Major Interrupt" check box is not set for scatter/gather channel 0. When I set it, it now works fine and the buffer is played properly. Here is the modification I made for scatter/gather configuration on both channels:
I've attached the final version of my test application if someone needs to do the same thing.
Thanks a lot for your help!!! It is really appreciated!
Regards,
Hugo
Hi Senlent,
Thanks for your help. However, the DMA doesn't seem to work properly. The first element of the buffer is written in the B register of the eMIOS channel but the source address is not incremented and I get an interrupt twice within the PWM period while I should get one every 128 PWM period (the minor loop size is set to 256 for a 2 bytes transfer). To see that, I've added a pin toggle in the DMA ISR function.
Here is a screenshot of the TCD registers and eMIOS settings:
And here is a screenshot of the oscilloscope:
As you can see, I get two interrupts within a few microseconds when I should get only one every 0.00436907 seconds (1 / 29296.875 KHz (PWM frenquency) * 128).
Do you have any idea why?
Regards,
Hugo
Hi@h_bouchard
Could you please modified it like below shows.
Hi Senlent,
Thank you for your answer. However, that doesn't do what it should. I should get an interrupt when minor loop has done all its DMA transfers, which is set to 128 (at major loop iteration). Therefore, with a PWM period of (1 / 29296.875 KHz) * 128 transfers = 4.369067 ms. I can see on your screenshot that the period is ~3.413 us.
Also, the DMA is not reading from the buffer, only the first element is read and played. I don't see the TCDx_SADDR being incremented. Any idea why?
Regards,
Hugo
Hi Senlent,
Thank you for your answer. I want to do that to avoid having to have an interrupt at PWM frequency to write P_EMIOS_0->CH.UC[1].B. By having two buffers of 128 samples each allows me to play one buffer while updating the second. When one buffer is played, I get the ISR and then I can fill the other one with new PWM values. At the next ISR, the new values are played and then I can update the other buffer. In the sample application I provided, the PWM duty cycle values are constants but this was just for a test.
I'm working from home now so I don't have an oscilloscope to test but will test tomorrow. Thanks again for your help so far!
Regards,
Hugo
Hi Senlent,
After some tests, I figured that the ISR is called only when both buffers are played (every ~8.72 ms) on my side unlike on your oscilloscope screenshot. It seems normal to me because the "Enable Major Interrupt" check box is not set for scatter/gather channel 0. When I set it, it now works fine and the buffer is played properly. Here is the modification I made for scatter/gather configuration on both channels:
I've attached the final version of my test application if someone needs to do the same thing.
Thanks a lot for your help!!! It is really appreciated!
Regards,
Hugo
My question is how to configure the DMAMUX to link Emios PWM with DMA channel 0?
this can be done in "RM"
Hi Senlent,
Thank you for your answer. I did add the RM and set it up as you suggested:
However, I'm still not able to generate DMA request from EMIOS0 CH 1. Here is my setting of the DMA channel. Both elements ID are set up the same except that Element ID 0 links to Element ID 1 and Element ID 1 links to Element ID 0 to create a double buffering which never stops.
The "Enable Start" option is set for both Element ID. The DMA interrupt is triggered right after the DMA channel is configured (call to Mcl_SetDmaChannelScatterGatherConfig()). The PWM is initialized after that. Even if I comment out the PWM_Init function, the DMA interrupt is triggered which tells me that something else is triggering the DMA instead of EMIOS0 CH 1 as it is set up in "RM". Do you have any idea what else can trigger the DMA?
I've updated the test firmware with the latest changes (see firmware_test2.zip).
Thanks,
Regards,
Hugo
Hi@h_bouchard
Sorry for the later reply cause we're in overload.
please disable this option
enable emios0_ch1->FEN otherwise it won't generate a DMA request.
IP_EMIOS_0->CH.UC[1].C = (IP_EMIOS_0->CH.UC[1].C & ~(eMIOS_C_FEN_MASK)) | eMIOS_C_FEN(1);
(it should be have api to enable FEN bit but i don't fimilar with MCAL API)
"I've updated the test firmware with the latest changes (see firmware_test2.zip)."
Could you please double check it, because i did not see "firmware_test2.zip"