View previous topic :: View next topic |
Author |
Message |
georpo
Joined: 18 Nov 2008 Posts: 281 Location: Athens, Greece.
|
dpics33 uart2 DMA |
Posted: Wed Jul 09, 2014 3:52 pm |
|
|
Hello!
I am using the UART2 module on a dspic33fj32gp302
and I need to receive 8 bytes with DMA.
I already tested that the UART is receiving properly by polling the URXDA bit (U2STA.0) and then reading the U2RXREG.
When I use DMA, the DMA interrupt triggers when the correct number of bytes is received but the contents of the DMA buffer is garbage.
Code: |
#BANK_DMA
char UART2BUF[8];
#INT_DMA0
void DMA0_ISR(void){
//code to display the buffer contents...
}
|
Code: |
setup_dma(0, DMA_IN_UART2, DMA_BYTE);
dma_start(0, DMA_CONTINOUS, &UART2BUF[0] );
enable_interrupts(INT_DMA0);
|
I also tried to manually fill the buffer with known values just to check my "code to display the buffer contents" code.
It looks like the address of the buffer is wrong?
Please give me your opinions.
Thanks.
compiler 4.134 (even though I tried older versions too) _________________ George. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19510
|
|
Posted: Thu Jul 10, 2014 3:00 pm |
|
|
Make sure the compiler is setting bits 7, and 6 on U2STA to zero. It sounds as if it is (otherwise the interrupt wouldn't occur at the required place), but if this is wrong corrupted data will occur.
Double check the errata. I don't think any apply to this (unless you are using two stop bits).
Does it work on UART1?. |
|
|
georpo
Joined: 18 Nov 2008 Posts: 281 Location: Athens, Greece.
|
|
Posted: Thu Jul 10, 2014 5:32 pm |
|
|
Hello!
bits 6 and 7 of U2STA are 0.
The same problem appears with UART1.
The interrupt occurs but the buffer never gets updated with incoming data.
During initialization I fill the buffer with data:
Code: |
for(i=0;i<8;++i) UART2BUF[i]=65; //ASCII 'A'
|
and when the interrupt occurs and I read the buffer I get all 'A' which means that the buffer is never updated.
I am pretty sure it is an address problem. Maybe it is because of the dspic33fj32gp302. I remember trying something similar with a dspic33fj64gp802 and it worked. I guess I have to change the PIC and try. _________________ George. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19510
|
|
Posted: Fri Jul 11, 2014 1:30 am |
|
|
Try using the standard C shortcut for the array address:
dma_start(0, DMA_CONTINUOUS, UART2BUF);
I'd really suspect it is a version problem with your compiler(s). 4.134, is an old version, and it sounds as if the other's you have tried are older still...
I didn't keep the versions around this point, as a lot of problems seemed to appear, especially with the DsPIC.
Look at the .sym file (or use the symbol option in the IDE), and verify it is placing UART2BUF in the area above address 0x1400 (where DMA RAM starts). it could be just a slip in the device database, and it 'thinks' the RAM is somewhere else....
Running on a later compiler (4.141), it correctly places UART2BUF at address 0x1400, and loads the DMA0STx registers with 0 (to access the first bytes in this area).
I notice one 'oddity'.
Have 4.137 (fractionally later than your compiler), and one version a little older. 4.137, correctly loads DMACNT with 7. The older compiler loads it with 8. This means it'd try to transfer 9 bytes not 8, into an 8 byte array....
The current compilers all put the same values in the registers as 4.137
So I then 'bodged':
Code: |
#include <main33dma.h> //your fuses etc.
#BANK_DMA
char UART2BUF[7];
#BANK_DMA
char dummy; //reserve one extra byte to allow 8 values.
#INT_DMA0
void DMA0_ISR(void)
{
//code to display the buffer contents...
}
void main(void)
{
int i;
setup_dma(0, DMA_IN_UART2, DMA_BYTE);
dma_start(0, DMA_CONTINOUS, UART2BUF);
enable_interrupts(INT_DMA0);
for(i=0;i<8;++i) UART2BUF[i]=65; //ASCII 'A'
while (TRUE) ;
}
|
This results in the registers being loaded with the same values as the current compiler. It's a real 'nasty', since one is declaring a 7 element array, and then writing 8 elements to it, but it'd be worth trying and seeing if this changes anything..... |
|
|
newguy
Joined: 24 Jun 2004 Posts: 1907
|
|
Posted: Fri Jul 11, 2014 7:34 am |
|
|
I'd also suggest "manually" setting registers to see what happens as opposed to trusting the CCS functions. I've developed 3 different products in the last 2 years, all using the same dsPIC, all heavily using DMA. I used v4.141 of the compiler. Although I didn't actually try the CCS DMA functions, I did try their stock CAN code and quickly regretted it. |
|
|
georpo
Joined: 18 Nov 2008 Posts: 281 Location: Athens, Greece.
|
|
Posted: Fri Jul 11, 2014 8:35 am |
|
|
from the .sym file:
Code: |
F36-F37 log.data2
F36.1 atan.flag
F38-F39 log.p
F3A-F3B log.n
F3E-F45 ceil.x
F3E-F45 floor.x
F56-F5D CEIL_FLOOR.x
F5E CEIL_FLOOR.n
F5F.0 CEIL_FLOOR.s
F60-F67 CEIL_FLOOR.y
F68-F6F CEIL_FLOOR.res
F70-F77 CEIL_FLOOR.l
1380-13FF Stack
1400-1407 UART2BUF
ROM Allocation:
3092 @DIV3232B
0480 SetupADC
0348 @delay_ms1
3936 @MULFF
07C8 @SITOF
08DC @ADDFF
0812 @DIVFF
062C atoi
0E26 @MULFF64
0BD4 @SI64TOF64
|
UART2BUF is on the right address and occupies correct space 1400-1407 (8 bytes)
I also tried ccs v5.003. The result is the same.
How can I check that DMA0STx registers gets the correct value 0 (to access the first bytes in this area)? _________________ George. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19510
|
|
Posted: Fri Jul 11, 2014 8:53 am |
|
|
With 5.003, I'd expect it to not work. There was a bug with interrupt handling on the early V5 releases. |
|
|
georpo
Joined: 18 Nov 2008 Posts: 281 Location: Athens, Greece.
|
|
Posted: Fri Jul 11, 2014 9:17 am |
|
|
I think I already wasted too much time on ccs bugs.
I will just use a second pin as a RTS handshake to receive data when needed. I just wanted to avoid that and have the system handle it automatically. Thanks for the support guys!
If anything comes in mind please drop a line ;) _________________ George. |
|
|
jeremiah
Joined: 20 Jul 2010 Posts: 1348
|
|
Posted: Fri Jul 11, 2014 11:05 am |
|
|
Back some months ago, I remember someone else having issues with DMA and UART on a similar chip. The end result was that the documentation on the dma_start() method was not up to date and they needed to do something with the 4th optional parameter for that method for it to work.
I don't remember how related it was to your issue, but it might be worth checking out. I believe the thread occurred in Feb or March time frame, so a forum search for dma should give you a good starting point. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19510
|
|
Posted: Sat Jul 12, 2014 3:37 am |
|
|
Yes. That was the thread at:
<http://www.ccsinfo.com/forum/viewtopic.php?t=51920&highlight=pic+dma>
It was slightly more complex, since the poster was wanting to do a transfer smaller than the buffer. However the same fix would work for the incorrect setting used in the older compilers, using the third parameter to correctly set the size.
Best Wishes |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19510
|
|
Posted: Mon Jul 14, 2014 2:19 am |
|
|
I've had a little play.
Have you got a #use RS232 statement?.
Problem is that unless you have this, the UART baud rate is not programmed.
You also need the #PIN_SELECT statements to program the pins to be used.
So I added:
Code: |
#PIN_SELECT U2RX = PIN_B2
#PIN_SELECT U2TX = PIN_B3 //set these to suit your UART
#use RS232(UART2,STREAM=UART2,BAUD=115200,STREAM=U2)
//and
setup_uart(115200,U2);
dma_start(0, DMA_CONTINOUS, UART2BUF, 7);
|
The latter line corrects the size error with the older compilers.
The setup_uart line I added, since it seems as if the optimiser may not actually configure the UART, if there are not getc/putc lines in the code.
With this done, running on a sim, I seem to be getting a sensible result.
Only though if I use DMA for the transmit as well, and add an error interrupt for the UART.
This may relate to:
<http://www.microchip.com/forums/m706242.aspx>
I suggest also, you switch to ping_pong mode. With your current setup, and your relatively slow CPU clock, if the baud rate is high, there may be problems if you don't get into/out of the DMA interrupt quickly, with the data safely saved. |
|
|
|