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

SPI issue on PIC24FJ64GA004

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



Joined: 08 Nov 2013
Posts: 11
Location: Istanbul

View user's profile Send private message

SPI issue on PIC24FJ64GA004
PostPosted: Thu Oct 30, 2014 5:28 am     Reply with quote

Hi All,
I have trouble with SPI modules on PIC24FJ64GA004. I use two SPI in my project with software CS. One for external memory, one for nordic tranceiver chip.
Here is my setup for spi modules:
Spi1:
Code:
   #pin_select SDI1=PIN_B14
   #pin_select SDO1=PIN_C2
   #pin_select SCK1OUT=PIN_C1   
  #USE SPI(SPI1, MASTER, STREAM=FLASH_STREAM)   
...
main()
{
...

   setup_spi( SPI_MASTER | SPI_CLK_DIV_4| SPI_SAMPLE_AT_END | SPI_H_TO_L | SPI_XMIT_H_TO_L );
}

This spi1 is used for external flash.

spi2:
Code:

         #pin_select SDI2=RF24_MISO
      #pin_select SDO2=RF24_MOSI
      #pin_select SCK2OUT=RF24_CLK
      #USE SPI(SPI2, MASTER, BAUD=8000000, MODE=0, BITS=8, MSB_FIRST, STREAM=RF24_SPI)
...

      setup_spi2( SPI_MASTER | SPI_CLK_DIV_2| SPI_SAMPLE_AT_MIDDLE | SPI_L_TO_H | SPI_XMIT_L_TO_H   ); 


This one is used for nRF905 chip. That chip is a bit sensitive about SPI modes. #use_spi command is a bit buggy, so i set SPI mode2 by using setup_spi2..

Here is the problem.
When i use that spi in a function more than one. It somehow reset processor. here is example:

Code:

void  measure_power (void)
{                                                               
   v_max=0;                                                               
   v_min=255;                                                           
   i_max=0;                                                           
   i_min=255;                                                         
   vxi=0;                                                 
   for (int i=0;i<100;i++)
   {                                                     
      ext_flash_write(FLASH_DATA_CURRENT+i,current[i],1);                       
      ext_flash_write(FLASH_DATA_VOLTAGE+i,voltage[i],1);   
      tot_squarec+=(current[i]-127)*(current[i]-127);
      if(i_max<current[i])                   
         i_max=current[i];           
      if(i_min>current[i])                                       
         i_min=current[i];             
      if(v_max<voltage[i])                                   
         v_max=voltage[i];
      if(v_min>voltage[i])     
         v_min=voltage[i];
      tot_squarev+=(voltage[i]-127)*(voltage[i]-127);
      vxi+=(current[i]-127)*(voltage[i]-127);
   }                                                                                       
...
   delay_ms(10);               
//!   ext_flash_read(FLASH_CpDATA_ACTIVEPOWER,actpow,1);                       
//!   ext_flash_read(FLASH_CpDATA_TOTALPOWER,totpow,1);   
   totpow+=rms_current*rms_voltage;                   
   actpow+=vxi;     
   printf("ok then");     
//!   ext_flash_write(FLASH_CpDATA_ACTIVEPOWER,actpow,1);                       
//!   ext_flash_write(FLASH_CpDATA_TOTALPOWER,totpow,1);   
}


ext_flash_write and ext_flash_read function use spi1. So when i use that function, there is no problem with only 2 spi code inside the for loop. But,
Code:

void  measure_power (void)
{                                                               
   v_max=0;                                                               
   v_min=255;                                                           
   i_max=0;                                                           
   i_min=255;                                                         
   vxi=0;                                                 
   for (int i=0;i<100;i++)
   {                                                     
      ext_flash_write(FLASH_DATA_CURRENT+i,current[i],1);                       
      ext_flash_write(FLASH_DATA_VOLTAGE+i,voltage[i],1);   
      tot_squarec+=(current[i]-127)*(current[i]-127);
      if(i_max<current[i])                   
         i_max=current[i];           
      if(i_min>current[i])                                       
         i_min=current[i];             
      if(v_max<voltage[i])                                   
         v_max=voltage[i];
      if(v_min>voltage[i])     
         v_min=voltage[i];
      tot_squarev+=(voltage[i]-127)*(voltage[i]-127);
      vxi+=(current[i]-127)*(voltage[i]-127);
   }                                                                                       
...
   delay_ms(10);               
   ext_flash_read(FLASH_CpDATA_ACTIVEPOWER,actpow,1);                       
   ext_flash_read(FLASH_CpDATA_TOTALPOWER,totpow,1);   
   totpow+=rms_current*rms_voltage;                   
   actpow+=vxi;     
   printf("ok then");     
   ext_flash_write(FLASH_CpDATA_ACTIVEPOWER,actpow,1);                       
   ext_flash_write(FLASH_CpDATA_TOTALPOWER,totpow,1);   
}



This one with more spi function will reset cpu everytime. When i cancel last two line, it will usually reset cpu (not everytime). So, the problem is with spi!

Here is ext_flash functions..
Code:

int1 ext_flash_read(unsigned int32 addr, unsigned int8 *data, unsigned int32 len)
{
   if (FLASH_ADDR_INVALID(addr))
     return FALSE;

   _ext_flash_send(SPI_FLASH_INS_READ, FALSE);
   _ext_flash_send_address(addr);
   while(len--) { *data++ = FLASH_XFER(0); }
   _ext_flash_end();
   return TRUE;
}

int1  ext_flash_write(unsigned int32 addr, unsigned int8 *data, unsigned int32 len)
{
    unsigned int16  ucMargin;
    unsigned int16  bytes_to_write;   
    unsigned int32  ucRemainder;
    int1 ret;

   if (FLASH_ADDR_INVALID(addr))//validate address
     return FALSE;

   if (FLASH_ADDR_INVALID(addr+len))//check if memory space is available for data
     return FALSE;

   
   if (len < 1)
     return FALSE;

   if (ext_flash_busy())
      return FALSE;

    ucMargin = (unsigned int8) (~addr) +1;
    ucRemainder = len;
    while(ucRemainder>0)
    {
        if(ucMargin != FLASH_WRITE_BUFFER_SIZE)
        {
            bytes_to_write = ucMargin;
            ucMargin = FLASH_WRITE_BUFFER_SIZE;
        }
        else
            bytes_to_write = FLASH_WRITE_BUFFER_SIZE;
       
        if(ucRemainder <= bytes_to_write)
            bytes_to_write = ucRemainder;
           
        ret = ext_flash_page_write(addr, data, bytes_to_write);
        if(ret != 1)
            return FALSE;            // return immediately if Not successful
        addr += bytes_to_write;
        data += bytes_to_write;
        ucRemainder -= bytes_to_write;           
    }
    return TRUE;
}



And here is my fuses setup:
Code:
                   
#DEVICE *=16    PASS_STRINGS=IN_RAM    //I need PASS_STRINGS=IN_RAM
#DEVICE ADC=8   
#FUSES WPOSTS11                 //Watch Dog Timer PostScalar 1:8192
#FUSES WDT                         
#FUSES ICSP2                    //ICD uses PGC2/PGD2 pins                                                                                   
//#FUSES PROTECT                  //Code protected from reads       
#FUSES CKSNOFSM                 //Clock Switching is enabled, fail Safe clock monitor is disabled     
//!               
//!#FUSES FRC_PLL                  //Internal Fast RC oscillator with PLL
#use delay(internal=32000000 )         


Thanks for any advice. I am stucked with spi modules Smile
Regards,
Ufuk Safak
_________________
-ufuk safak-
Istanbul Technical University
JamesW



Joined: 23 Apr 2007
Posts: 91
Location: Rochester, England

View user's profile Send private message Visit poster's website

PostPosted: Thu Oct 30, 2014 5:46 am     Reply with quote

Can you add in any form of debug?

The routine restart_cause() will return the reason that the processor restarted. (The list of causes is in the device.h file)

Code:

fprintf(DEBUG_PORT,"\r\n\r\n RESTART : CAUSE %02u", restart_cause());


Knowing why the processor has restarted, will be a good starting point

James
SuperDave



Joined: 22 May 2008
Posts: 63
Location: Madison, TN

View user's profile Send private message Visit poster's website

PostPosted: Fri Oct 31, 2014 2:15 pm     Reply with quote

Two quick thoughts:

1. Both ext_flash_write and ext_flash_read return values which you are neither testing nor even viewing. At the debug level I'd be inclined to write a loop at each call, for example

myStatus = false;
repeat
light a led or pulse a pin you can see with a scope
myStatus = ext_flash_write (your stuff)
unlight the led/pin
small unique delay
until (myStatus != false);

The problem with this loop is that it will hang if the spi never works so only do it in debug but even the completed code should not go to the second (or third or fourth) write until the first (previous) is done successfully. If you use a scope the pin will go positive for the length of spi transmission and the 'small unique delay' will tell you which spi transmission you are looking at if it hangs. Come to think of it, the particular spi enable pin should be all you need if you have a good scope. You can also change the write and read routines to return more than just false or true.

2. Be sure the variables that result from a * b have enough room for the largest possible number.
Ttelmah



Joined: 11 Mar 2010
Posts: 19535

View user's profile Send private message

PostPosted: Fri Oct 31, 2014 3:42 pm     Reply with quote

#USE SPI, and setup_spi, should not be used together.

There are two separate SPI mechanisms in CCS. The 'old' one, is setup_spi, used with spi_read, and spi_write. The 'new' one is #USE SPI, with spi_xfer.

If you look at the manual, you will see that #USE SPI, does not refer at any point to spi_read spi_write, or setup_spi. Similarly, setup_spi, does not refer to #USE SPI, or spi_xfer.

Use only one or the other. Preferable #USE. Change this line to select the required clock edges etc. (preferably just use a mode number). Then ensure you only use spi_xfer to do the actual transfers. Mixing the two systems can cause problems. They are not designed to be used together. Setup_spi, spi_read, and spi_write, are there for 'legacy compatibility'.....

You don't mention compiler version?. #USE has been working well for several versions now. If it is not working, then don't use it at all. Just use the older commands.
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