I'm trying to set up SSI_LDD to use DMA, so it created DMAChannel_LDD subcomponents, but field that I need to change are greyed out, such as source start address. Am I missing something or is there a problem with this component?
anyone home? not sure how anyone could use this module with this bug present!?
Update: If I create a DMAChannel_LDD outside of the SSI_LDD then those fields all work. It's only when you enable DMA inside SSI_LDD and it creates subordinate DMAChannel_LDD's (I set one for each of the two TX pins) Unfortunately there's no way to link that external one into the SSI_LDD.
generally SSI_LDD should behaves the same in all modes (polling, interrupts, DMA, etc...)
Run-time settings are pointer to user data and number of requests count. The rest of settings is set according to configuration in SSI_LDD.
regarding Source transaction settings:
Start address - should be set in run-time by SendBlock method in SSI_LDD (for more details please see attached screen-shot).
Transaction count - is controlled by Watermark property in SSI_LDD.
Address adjustment - 4 is set due to SSI_LDD component correct functionality (This item is controlled by Data Type in SSI_LDD).
regarding Destination transaction settings:
Address adjustment - 0 is set due to SSI_LDD component correct functionality.
regarding Transfer transaction settings:
Transaction size - is controlled by Data Type in SSI_LDD.
Request count - should be set in run-time by SendBlock method in SSI_LDD (for more details please see attached screen-shot).
We will try improve hints in DMA_Channel component for next release of PEx.
Processor Expert Support Team
You forgot the screen shot....
Let me tell you what I'm trying to do.
I have 8 channels of audio, let's say each sample is an int_32. They are organize in memory to make signal processing easy:
#define AUDIO_CHANPEROUT 4 ///< i4s format
#define AUDIO_NOUTS 2 ///< 2 TX outputs per SAI
#define AUDIO_NOUTPUTCHANNELS AUDIO_CHANPEROUT * AUDIO_NOUTS
#define AUDIO_OUTPUTBUFSIZE 16 ///< samples per channel for audio output buffer
I'm setting each of the two TX outputs to i4s format (2 channels per stream). Tx0 outputs channel 1-4, Tx1 outputs channel 5-8.
Once the program starts, the audio *must* run continuously. This is the usual case with audio (except the case of low power sleeping, we'll ignore that for now).
So the indices for the buffer are, in order:
- output channel 0-7
- pingpong = 0 or 1
- sample number 0-16
So when I have a DSP loop, I process 16 samples of one channel, then go to the next. Most efficient way to do it in general. That would happen in the "halfway there" DMA interrupt, which would also increment (mod 2) the pingpong index.
I let the DMA controller do the hard work. I set the FIFO request in the SSI to 4. So then the DMA will get 4 words in 1 minor loop, which is the 4 channels of one sample for one output. So the minor loop has to skip by 32 samples each time to get to the next channel. Then, it has to skip 4 whole channels to get to the next sample, as those channels are handled by the other Tx output. So that's the adjustment after the minor loop. Then, after the major loop, do another adjustment to reset the address back to the beginning, and chain the DMA to itself. Then the processor never has to get involved once it starts.
So in this case, I believe the DMA settings I want are thus:
start address: &audioBuf
transaction size: 32-bits
address adjustment: 128
start address: (LDD_DMA_TAddress)(I2S_PDD_GetTxDataChannelRegAddress(I2S0_BASE_PTR,0U))
address adjustment: 0
transactions count: 4
request count: 32
After request complete actions:
source address adjustment: -508 (skip back to beginning but one sample ahead 512-4)
After transfer complete actions:
channel linking: enabled, DMA0 (same channel)
source address adjustment: -636 (skip back to beginning 512+128-4)
start address: &audioBuf
start address: (LDD_DMA_TAddress)(I2S_PDD_GetTxDataChannelRegAddress(I2S0_BASE_PTR,1U))
source address adjustment: -508
channel linking: enabled, DMA1 (same channel)
source address adjustment: -636
... if this makes sense, then you can see why I want to access those greyed out fields.
NOTE: I edited this with updated values thanks to source code in Earl Goodrich's post here: Re: is there any demo code for using I2S?
I implemented this and tested it by:
1. created SSI_LDD and enabled DMA
2. generated PE code
3. disabled generating PE code for the audio SSI_LDD module
4. once disabled, then disable DMA in the SSI_LDD interface and save (to avoid conflicts with below)
5. deleted the DMA source files
6. created two DMAChannel_LDD components (outside of SSI_LDD)
7. renamed them the same name as the deleted DMA components
8. made sure I generate the needed methods
9. generate the PE code of these
10. disable generating the PE code after generating once
11. delete the extra events in Events.c (since the ones I want are in Audio0.c)
12. added the 'halfway' interrupt flag and other bug fixes noted in other of my recent posts
Its running and seems to be working fine. Setting the bus throttle-back to 8 cycles in the two DMA engines seems to have a positive effect overall.
In sum, this setup should be allowed in the component, as it's usual way to do audio.
UPDATE: now that I understand the DMA engine a little better, I realize I can't do what I want with the setup above. I was getting very weird response.
It also showed another bug - you can't assign two DMA channels to the same source, or else results are unpredictable. The PE component doesn't catch that.
Turns out I can do what I wanted (8 non-interleaved pingpong buffers to two I4S streams), using 8 DMA channels and the PIT. So actually blowing off these PE drivers and simply using the Init_I2S, Init_DMA, and Init_PIT and literally one other line of code to enable the I2S after everything was set up, and it's working 100%, with much less code (the Init_xxx drivers are quite lean) and way less confusion.
I suggest the PE team write some actual working tests for the Audio_LDD driver - you'll find the defaults are not at all helpful.
Thank you for the feedback, it has been passed to the development team. I'm glad that you have been able to implement the solution that you needed.
The solution with Init components and direct access to the hardware will in most cases be faster and more effective than the higher level components (LDD) .
It's a price for having the general drivers that are not tailored for a specific task and are available on many (sometimes different) platforms (but I'm not saying that it should not be improved :-).
In cases like this, Init_xxx components accompanied with PDD macros are a good tool to achieve optimized code for a specific task.
Well in this case, the design pattern for the SSI_LDD is not appropriate for the peripheral's intended use. If your team disagrees, I would like to see them produce a working example - let's say, something simple like streaming audio in, and doing some DSP for example attenuation based on the pot position on the TWR board, and then stream back out, on the TWR-K60F120M board. I don't think it's possible using that component as it is.
Retrieving data ...