CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

dspic SPI DMA

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
georpo



Joined: 18 Nov 2008
Posts: 274
Location: Athens, Greece.

View user's profile Send private message

dspic SPI DMA
PostPosted: Sat Jul 28, 2018 10:47 am     Reply with quote

Hello again,

I am using a dspic33fj64gp804 to send out SPI data to neopixel LEDs.
Anyway, I already got it working and now I want to do it with DMA to save some cpu cycles because each transfer is 240 bytes.

Code:

   #BANK_DMA
   unsigned char SPI2Buff[240];

   setup_dma(6,DMA_OUT_SPI2,DMA_BYTE);   


void DMATest(){
   int p=0;

   for(p=0;p<240;++p) SPI2Buff[p]=0b11010001; //fill the buffer with known data

   while(1){

    dma_start(6, DMA_ONE_SHOT | DMA_FORCE_NOW, &SPI2Buff[0],239);

    delay_ms(10);

   }

}

      




The problem is that in my oscilloscope I see only the 1st byte repeating.
Nothing more.

Any ideas??


[img]https://ibb.co/eW9wR8[/img]
_________________
George.


Last edited by georpo on Sat Jul 28, 2018 11:17 am; edited 1 time in total
temtronic



Joined: 01 Jul 2010
Posts: 9081
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Sat Jul 28, 2018 11:01 am     Reply with quote

hmm.. the way I see your code is that every byte of the buffer contains the same data ??
Quote:
for(p=0;p<240;++p) SPI2Buff[p]=0b11010001; //fill the buffer with known data

so everything you see is the same.

Jay
georpo



Joined: 18 Nov 2008
Posts: 274
Location: Athens, Greece.

View user's profile Send private message

PostPosted: Sat Jul 28, 2018 11:06 am     Reply with quote

Yes of course they are the same.
This is just to send some known values that I can recognize in the oscilloscope.
The problem is that I see only 1 byte of data.
I should see a stream of 240 bytes with the same value of course.
_________________
George.
georpo



Joined: 18 Nov 2008
Posts: 274
Location: Athens, Greece.

View user's profile Send private message

PostPosted: Sat Jul 28, 2018 12:07 pm     Reply with quote

From a search in Microchip forum other people have this problem also.
It has to do with the SPI receiver that accepts data as you transmit but no one handles this data so the spi module overruns.

In my case I have enabled only the SDO. No clock, NO SDI.
So my module does not receive data...
_________________
George.
georpo



Joined: 18 Nov 2008
Posts: 274
Location: Athens, Greece.

View user's profile Send private message

PostPosted: Sat Jul 28, 2018 12:25 pm     Reply with quote

Definitely has to do with SPI receiver.
I am tracking bit SPIROV (Receive Overflow Flag bit) and it is SET which proves my assumption.

I set up interrupt #INT_SPI2 to read the buffer and now my DMA transmit works.

Code:

#INT_SPI2

void SPI2ISR(){
   char aa=0;

   aa=SPI2BUF;
}



The point is that it is useless because I want to use DMA. Not interrupt. It is a waste of time.

So, now I have to set another DMA channel to SPI receive.
Any help here?
_________________
George.
georpo



Joined: 18 Nov 2008
Posts: 274
Location: Athens, Greece.

View user's profile Send private message

PostPosted: Sat Jul 28, 2018 12:56 pm     Reply with quote

Finally solved. I use channel 7 to receive from SPI:
Code:

setup_dma(7, DMA_IN_SPI2, DMA_BYTE);      //use DMA channel 7 for SPI2 DATA IN (dummy)
dma_start(7, DMA_CONTINOUS ,&SPI2InBuff[0],239);   //setup dummy receive to avoid SPI2 overrun

It is really strange though because no data is being shifted in to the SDI.
I am only using the SDO.
Where does this data come from??
Anyway problem solved.
_________________
George.
Ttelmah



Joined: 11 Mar 2010
Posts: 19195

View user's profile Send private message

PostPosted: Sat Jul 28, 2018 1:32 pm     Reply with quote

SPI is always bi-directional. If the pin is not defined it'll just be random....

You also need to set the DMA to increment the source address. Otherwise it is just going to keep sending the first byte....
Look at the defines for your chip (the syntax varies according to the nature of the DMA unit, and I'm not on a computer with CCS installed at the moment, so can't check what it is for this chip).
Have just checked, and for this chip the increment is automatic. Unlike many of the chips which have separate controls for increment source or destination this only has two modes, designed for 'peripheral to RAM' or 'RAM to peripheral', and in each case the RAM address always increments.

The receive buffer to prevent the SPI hang, can be tiny. Four bytes is ideal. No need to have the same size buffer as your TX. Using continuous, it'll loop and re-use the buffer.
georpo



Joined: 18 Nov 2008
Posts: 274
Location: Athens, Greece.

View user's profile Send private message

PostPosted: Sun Jul 29, 2018 8:35 am     Reply with quote

Yes, I got it.
Thanks for the support guys!!!

I set the receive buffer to 4 bytes. It is all good.

BTW. What happens if I omit the last parameter: the 239 in the example below:

Code:

dma_start(7, DMA_CONTINOUS ,&SPI2InBuff[0],239);


Will it wait for 240 bytes?
_________________
George.
Ttelmah



Joined: 11 Mar 2010
Posts: 19195

View user's profile Send private message

PostPosted: Sun Jul 29, 2018 11:07 am     Reply with quote

If you are using a four byte buffer, it needs to be 4 (or possibly 3 - see below).

Using 'continuous' it'll repeat using the same buffer, whenever data arrives.
Every four bytes (when the buffer is filled), it'll issue a DMA interrupt (so if you wanted the data you could do something with it), but you simply ignore this.
The count tells the controller when to reset the index count in the buffer (and interrupt unless half count interrupting is enabled).
Get the manual 70182C.pdf (from MicroChip). This is vital reading for anyone using DMA. Look at 22.6.8. The number in this setup, is DMACMT.

You need to check whether your chip has type1 or type2 DMA. On Type1, this needs to be one less than the count to transfer (so 3). On Type2, the count required....

Just checked and this chip is type1, so needs 1 less than the count (3).
georpo



Joined: 18 Nov 2008
Posts: 274
Location: Athens, Greece.

View user's profile Send private message

PostPosted: Sun Jul 29, 2018 10:59 pm     Reply with quote

Yes, It is already setup for 4 bytes buffer and with 3 in count.

Thank you very much for the responses!
_________________
George.
Ttelmah



Joined: 11 Mar 2010
Posts: 19195

View user's profile Send private message

PostPosted: Mon Jul 30, 2018 12:52 am     Reply with quote

On your 'omitting the last value', you can't do this.

Except you can.... Very Happy

The DMA count register _must_ be initialised. If you look at the DMA data sheet, it says:
Quote:

Initializing DMA transfer count must be initialized (see 22.5.4 “DMA Transfer Count Set
Up”)

The count value must be specified.

The point about the function version without this setting, is that the register retains what it was last set to. So for example, you can start the DMA once with a count, and then on subsequent starts, omit the count. So if using 'one shot' mode, send the the repeated commands to do a transfer, just with the peripheral address and the buffer address, but no count.
What you must not do it trigger the first DMA on a particular channel without a count.... Sad
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group