|
|
View previous topic :: View next topic |
Author |
Message |
fuxafak
Joined: 08 Nov 2013 Posts: 11 Location: Istanbul
|
SPI issue on PIC24FJ64GA004 |
Posted: Thu Oct 30, 2014 5:28 am |
|
|
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
Regards,
Ufuk Safak _________________ -ufuk safak-
Istanbul Technical University |
|
|
JamesW
Joined: 23 Apr 2007 Posts: 91 Location: Rochester, England
|
|
Posted: Thu Oct 30, 2014 5:46 am |
|
|
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
|
|
Posted: Fri Oct 31, 2014 2:15 pm |
|
|
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: 19499
|
|
Posted: Fri Oct 31, 2014 3:42 pm |
|
|
#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. |
|
|
|
|
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
|