- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
I am developing a simple application where I have a counter design in UDB. The counter value is written into a status register.
I have a DMA which is triggered by CPU_REQ , which transfers the 8 bit counter value to the VDAC. The output at the VDAC should be a saw tooth wave. However I am not gettin the same. When I use a Timer to trigger the DMA req as well as the counter, I am able to get the sawtooth wave. Could anybody please help me with this. Following is my main.c file
#include <device.h>
void main()
{ uint8 channel;
uint8 td;
#if (defined(__C51__))
// channel = DMA_DmaInitialize(1, 1, 0, 0);
channel = DMA_DmaInitialize(0, 0, 0, 0);
#else
// channel = DMA_DmaInitialize(1, 1, HI16(Status_Reg_sts_reg__STATUS_REG), HI16(VDAC8_viDAC8__D) );
channel = DMA_DmaInitialize(0, 0, HI16(Status_Reg_sts_reg__STATUS_REG), HI16(VDAC8_viDAC8__D) );
#endif
while(1){
td=CyDmaTdAllocate();
if(td!=DMA_INVALID_TD)
break;
}
CyDmaTdSetConfiguration(td, 1, td,0 );
CyDmaTdSetAddress(td, LO16((uint32)Status_Reg_sts_reg__STATUS_REG), LO16((uint32)VDAC8_viDAC8__D) );
CyDmaChSetInitialTd(channel, td);
CyDmaChPriority(channel,0);
CyDmaChEnable(channel, 1);
CyDmaChSetRequest(channel, CPU_REQ);
Timer_Start();
VDAC8_Start();
for(;;)
{
// VDAC8_SetValue(Status_Reg_Read());
/* Place your application code here. */
}
}
Regards
meenz
Solved! Go to Solution.
- Labels:
-
PSoC 5LP
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
As an add on to the previous experiment, instead of output to VDAC, I want to read back the counter value through UART. So basically the flow would be Counter->DMA->Buffer After DMA transfer is complete,read buffer data through UART.
What is happening is that in the read back data, the count value increases in steps of 4/5 instead of continuously increasing. Does each DMA operation take 5 cycles for burst read? As per my understanding from previous posts, after the initial latency, I should expect a new data every cycle when the REQUEST_PER_BURST is set to '0'. following are the DMA settings.
uint8 buffer[4096];
/// Burst count is 1 ; After the initial CPU request, execute all other bursts continuously;
#if (defined(__C51__))
channel = DMA_DmaInitialize(1, 0, 0, 0);
#else
channel = DMA_DmaInitialize(1, 0, HI16(Status_Reg_sts_reg__STATUS_REG), HI16(buffer) );
#endif
////// Allocate TD
while(1){
td=CyDmaTdAllocate();
if(td!=DMA_INVALID_TD)
break;
}
/// Execute TD and stop. Increment only destination addr
CyDmaTdSetConfiguration(td, 4095, DMA_INVALID_TD,(TD_INC_DST_ADR) );
CyDmaTdSetAddress(td, LO16((uint32)Status_Reg_sts_reg__STATUS_REG), LO16((uint32)buffer) );
CyDmaChSetInitialTd(channel, td);
CyDmaChPriority(channel,0);
CyDmaChEnable(channel, 1);
/// Start DMA
CyDmaChSetRequest(channel, CPU_REQ);
Regards
meenz
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hey Meenz, are you using UDB based Counter or built a Custom Counter component using component creation tool?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- When you trigger the DMA and the counter using same clock(in this case, a Timer), DMA and the counter operates at the rate determined by input clock. Hence every incremental count from the counter is effectively transferred by DMA. DMA takes only one BUS CLOCK cycle.
- However, when the DMA is trigger in CPU, you might be triggering it continuously and each transfer finishes in one BUS Clock period. The counter increments at the rate determined by the Timer. Hence the values transferred from the status register to DAC will be irregular. After every CPU trigger it might be necessary to wait until the counter has incermented and then move on to the next step.
I hope this helps !
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi U2,
Thanks for the quick response. However I have one doubt. When running DMA in CPU mode, The counter is incremented continuously at bus clock. The Timer dependency does not exist for both DMA and the counter. In such a scenario I expect that every BUS clock, my counter value is incremented and the DMA transfers this value to the DAC. However, I am not getting any output at the DAC other than a DC level.
Regards
Meenz
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Couple of observations
- VDAC Configuration: The VDAC_Speed is set to Slow, hence settling time is higher, you might want to change it to fast to improve settling time at the output.
- Output Range in your project is set to 0-4V. In this case the maximum updaterate of VDAC component is 250Ksps. This will be the limit on the output update rate. So even if your DMA is capable of transferring the data at Bus Clock(24 Mhz) DAC is not capable of updating. Reduce the output range to 0-1V to get a output rate of 1MSPS(4X of 0-4V range ).
DMA Configuration:
- In your project if you intend to perform CPU trigger, the parameter of interest is the REQUEST_PER_BURST parameter in the API, DMA_DmaInitialize(). If this parameter is set to 1, it is required to provide a CPU request for every transfer. Hence in your project since CyDmaChSetRequest(channel, CPU_REQ) is called only once, only first transfer would occur. If the parameter REQUEST_PER_BURST is set to zero then the DMA will transfer number of bytes as specified by TD(In your case it is 1). Hence you would get a DC value as seen by you.
- DMA takes 6 cycles for transferring data if the REQUEST_PER_BURST parameter is set to 1. Be it CPU or External trigger given to DRQ terminal it requires 6 cycles for the DMA to fetch address from TD and complete the transfer. However if this parameter is set to zero, only the first byte transfer will take 6 cycles. Every other transfer will take 1 cycle.
I hope these things should get you going.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi U2,
Thanksa lot for your response. In my project I required that the td of length 1 byte be executed continuously. So the REQUEST_PER_BURST was set to '0' as mentioned by you. In addition to that I made one more change. I set the TD_AUTO_EXEC_NEXT in CyDmaTdSetConfiguration(). With this setting I was able to get the expected output.
Thanks a lot for your help
Regards
meenz
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
As an add on to the previous experiment, instead of output to VDAC, I want to read back the counter value through UART. So basically the flow would be Counter->DMA->Buffer After DMA transfer is complete,read buffer data through UART.
What is happening is that in the read back data, the count value increases in steps of 4/5 instead of continuously increasing. Does each DMA operation take 5 cycles for burst read? As per my understanding from previous posts, after the initial latency, I should expect a new data every cycle when the REQUEST_PER_BURST is set to '0'. following are the DMA settings.
uint8 buffer[4096];
/// Burst count is 1 ; After the initial CPU request, execute all other bursts continuously;
#if (defined(__C51__))
channel = DMA_DmaInitialize(1, 0, 0, 0);
#else
channel = DMA_DmaInitialize(1, 0, HI16(Status_Reg_sts_reg__STATUS_REG), HI16(buffer) );
#endif
////// Allocate TD
while(1){
td=CyDmaTdAllocate();
if(td!=DMA_INVALID_TD)
break;
}
/// Execute TD and stop. Increment only destination addr
CyDmaTdSetConfiguration(td, 4095, DMA_INVALID_TD,(TD_INC_DST_ADR) );
CyDmaTdSetAddress(td, LO16((uint32)Status_Reg_sts_reg__STATUS_REG), LO16((uint32)buffer) );
CyDmaChSetInitialTd(channel, td);
CyDmaChPriority(channel,0);
CyDmaChEnable(channel, 1);
/// Start DMA
CyDmaChSetRequest(channel, CPU_REQ);
Regards
meenz
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi Meenz,
In your project since the burst count is set to 1, the DMA chain terminates after one transfer. As a result the entire TD configuration needs to be reloaded after one transfer and everytime. This will eat up some time. Increase the Burst count to maximum of say 127(maximum allowed) to avoid this delay.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
hi,
I need urgent help to implement a UDB or a documented example of implementation in UDB
thank you in advance.
bye
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi Meenz
I need urgent help to implement a UDB or a documented example of implementation in UDB
best regards.
bye
Bonjour l'ami
J'ai besoin d'aide pour comprendre comment implémenter un UDB block reconfigurable de CYpress avec un PSOC5
Merci d'avance.
Cordialement
EBK
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
U2 or others:
What is the significance of setting Request per burst to 0? Does this make the DMA operate continuously? What if the number were greater than 1, would you have to perform more than one request to get the DMA to respond? Thanks.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi porcine_aviator,
The Request Per Byte should always be either a 0 or 1.
If the Request per Burst is set to 0, then all the subsequest bursts after the first burst will be automatically requested and carried out.
If the Request per Burst is 1, then all the subsequent bursts after the first burst must also be individually requested.
Regarding your question about using a value other than 0 and 1, it is not advisable to do it. In the API implementation, the "RequestPerBurst" value is ANDed with 0x01 and left shifted 7 times. Hence, the value will be sent to MSB which will determine whether Request per Burst is enabled or not.
Hence, if you use an even number (with LSB = 0), then it is equivalent to giving Request per Burst as 0. If you use an odd number (with LSB = 1), then it is equivalent to giving Request Per Burst as 1.
Hope this helps.