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 CCS Technical Support

Help with PIC24EP512GP202 SPI and DMA(Solved)

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



Joined: 02 Feb 2011
Posts: 14

View user's profile Send private message

Help with PIC24EP512GP202 SPI and DMA(Solved)
PostPosted: Wed May 22, 2019 7:15 am     Reply with quote

Hi all,

Sorry, but this thing is make me crazy for days.

I try to use SPI (thanks Ttelmah for this) to transmite 124 bytes to other chip in master mode this works fine.

Now i am trying to put the DMA to work and again i can only transmit the first 3 bytes or many garbage bytes. I don't know again what i made wrong.

I saw all posts in this forum about this.

Compiler version 5.085.

Thanks in advance.

My test code is:
Code:

#include <24EP512GP202.h>

#device ICSP=3

#use delay(clock=140000000,crystal=8000000,restart_wdt)

#FUSES NOWDT                    //Watch Dog Timer
#FUSES WPRES32                  //Watch Dog Timer PreScalar 1:32
#FUSES WPOSTS11                 //Watch Dog Timer PostScalar 1:1024
#FUSES NOJTAG                     //JTAG disabled
#FUSES WDTWIN_25%               //Watchdog Window is 25% of WDT period
#FUSES PLLWAIT                  //Clock switch to PLL will wait until the PLL lock signal is valid
#FUSES WINDIS                   //Watch Dog Timer in non-Window mode
#FUSES OSCIO                    //OSC2 is general purpose output
#FUSES IOL1WAY                  //Allows only one reconfiguration of peripheral pins
#FUSES NOCKSNOFSM               //Clock Switching is disabled, fail Safe clock monitor is disabled
#FUSES PR_PLL
#FUSES HS


unsigned int8 Buff1[124];

#BANK_DMA #byte SPI1BUF=getenv("SFR:SPI1BUF")// i try this
//#byte SPI1BUF=getenv("SFR:SPI1BUF") // and this


 #use spi(FORCE_HW,MASTER,SPI1,MODE=0,BITS=8,stream=SPI_PORT1,BAUD=8000000,DO=PIN_B8,CLK=PIN_B7)

int1 dma1_ready=1;

#INT_DMA1
void  dma1_isr(void) {

   output_low(pin_b4);// Led for debug
   dma1_ready=1;

}



void main() {

   unsigned int8 p=0;

   setup_vref(VREF_DISABLED);
   
   setup_dma(1,DMA_OUT_SPI1,DMA_BYTE);

   for(p=0;p<124;p++) Buff1[p]=0x2f;

   enable_interrupts(INT_DMA1);
   enable_interrupts(INTR_GLOBAL);

 while(TRUE) {

if(dma1_ready) {

         delay_ms(100);

         output_high(pin_b4);
         
         delay_ms(100);
         
         dma1_ready=0;
         
 dma_start(1,DMA_ONE_SHOT|DMA_FORCE_NOW,SPI1BUF,&Buff1[0],124-1);
   
      }

}


Last edited by pbraida on Wed May 22, 2019 3:07 pm; edited 2 times in total
pbraida



Joined: 02 Feb 2011
Posts: 14

View user's profile Send private message

PostPosted: Wed May 22, 2019 7:56 am     Reply with quote

Hi all,

This lines are wrong.

#BANK_DMA #byte SPI1BUF=getenv("SFR:SPI1BUF")// i try this
//#byte SPI1BUF=getenv("SFR:SPI1BUF") // and this

The BANK_DMA is

unsigned int8 Buff1[124];

Sorry.
Ttelmah



Joined: 11 Mar 2010
Posts: 19568

View user's profile Send private message

PostPosted: Wed May 22, 2019 8:44 am     Reply with quote

Yes. The #BANK DMA tells the compiler where to put the memory block that
the DMA transfers are done to/from. It has to be located in the DMA memory
'area' in the RAM.
pbraida



Joined: 02 Feb 2011
Posts: 14

View user's profile Send private message

PostPosted: Wed May 22, 2019 8:56 am     Reply with quote

Yes, but it's still not working.

The above error was when copying the code to the message.

I still need help.

Pedro.
Ttelmah



Joined: 11 Mar 2010
Posts: 19568

View user's profile Send private message

PostPosted: Wed May 22, 2019 1:54 pm     Reply with quote

Your SPI command just needs:

#use spi(MASTER,SPI1,MODE=0,BITS=8,stream=SPI_PORT1,BAUD=8000000)

Then your DMA command needs:
dma_start(1,DMA_ONE_SHOT|DMA_FORCE_NOW|DMA_PERIF_ADDR,DMA_OUT_SPI1,Buff1,124-1);

Note the DMA_PERIF_ADDRESS, and DMA_OUT_SPI1.

Why 124-1?. The dma transfer count is not like a timer. It is the number
of bytes to transfer.
pbraida



Joined: 02 Feb 2011
Posts: 14

View user's profile Send private message

PostPosted: Wed May 22, 2019 3:06 pm     Reply with quote

Ttelmah,

After many hours of tries and errors and with a help of CCS support.

The main issue is:

I only use the tx pin, but this PIC24 doesn't have any way of disabling the receiver part of the SPI peripheral.
However i wasn't reading the received data and this was causing it overflow the HW receive buffer which caused it to stop transferring data when that happened. To fix this I added a second DMA channel to read the receive data as well.

Thanks a lot for your help.

Pedro.
pbraida



Joined: 02 Feb 2011
Posts: 14

View user's profile Send private message

PostPosted: Wed May 22, 2019 3:14 pm     Reply with quote

This is the functional test code to help anyone with the same problem:

Code:
#include <24EP512GP202.h>
#device ICSP=3
#use delay(internal=140MHz)

#FUSES NOWDT                    //Watch Dog Timer
#FUSES WPRES32                  //Watch Dog Timer PreScalar 1:32
#FUSES WPOSTS11                 //Watch Dog Timer PostScalar 1:1024
#FUSES NOJTAG                     //JTAG disabled
#FUSES WDTWIN_25%               //Watchdog Window is 25% of WDT period
#FUSES PLLWAIT                  //Clock switch to PLL will wait until the PLL lock signal is valid
#FUSES WINDIS                   //Watch Dog Timer in non-Window mode
#FUSES OSCIO                    //OSC2 is general purpose output
#FUSES IOL1WAY                  //Allows only one reconfiguration of peripheral pins

#bank_dma
unsigned int8 Buff1[8400];

#bank_dma
unsigned int8 rxByte;

int1 dma1_ready=1;

#use spi(FORCE_HW,MASTER,SPI1,MODE=0,BITS=8,stream=SPI_PORT1,BAUD=8000000,DO=PIN_B8,CLK=PIN_B7)

#INT_DMA1
void  dma1_isr(void) {

   output_low(pin_b4);// Led for debug
   dma1_ready=1;

}

void main() {

   unsigned int16 p=0;

   setup_dma(1,DMA_OUT_SPI1,DMA_BYTE);
   setup_dma(2,DMA_IN_SPI1,DMA_BYTE);

   for(p=0;p<8400;p++) Buff1[p]=0xaa;
     
   enable_interrupts(INT_DMA1);
   enable_interrupts(INTR_GLOBAL);
   
   while(TRUE) {
   
      if(dma1_ready) {
     
         delay_ms(100);
         output_high(pin_b4);
         delay_ms(100);
         
         dma1_ready=0;
         
         dma_start(2,DMA_CONTINOUS,&rxByte,0);
         dma_start(1,DMA_ONE_SHOT|DMA_FORCE_NOW,&Buff1[0],8399);
         
      }
   }
}
Ttelmah



Joined: 11 Mar 2010
Posts: 19568

View user's profile Send private message

PostPosted: Thu May 23, 2019 12:17 am     Reply with quote

Yes, Makes sense. SPI transfers are always two way.
On my own code that DMA bursts a config sequence, I still run my DMA
receive code as well.

On the UART, there is a master 'enable', and a separate transmit enable,
so you can enable just the receive (but you can't enable just the transmit).
On the SPI, there is only a single enable, with the comment:

SPIEN: SPIx Enable bit
1 = Enables the module and configures SCKx, SDOx, SDIx and SSx as serial port pins

So, no option to transmit alone.

That it always needs to be 'two way', has been mentioned before here.
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