Page 1 of 1

MOD54415 peculiar QSPI issue

Posted: Thu May 02, 2013 7:24 am
by nicobari
Hi,
I am trying to read data from an IMU (http://www.analog.com/static/imported-f ... S16488.pdf). The way this works is, netburner sends a comamnd to IMU via SPI3 and IMU responds with the corresponding data. So my code looks like.

Code: Select all

#define	xahigh 0x00001E00 //command to IMU for MSB of Xaccel
#define	yahigh 0x00002200 //command to IMU for MSB of Yaccel
#define	zahigh 0x00002600 //command to IMU for MSB of Zaccel

void initIMUspi()
{
	J2[21].function(1);//SPI3 Input
	J2[22].function(1);//SPI3 Out
	J2[23].function(1);//SPI3 chip select 0
	J2[24].function(1);//SPI3 clock

	sim1.dspi3.ctar[0]=0x7E020006; //SPI Transfer protocol
}

void readIMU()
{
	sim1.dspi3.pushr=0x04FF0000|xahigh;
	sim1.dspi3.pushr=0x04FF0000|yahigh;
	sim1.dspi3.pushr=0x04FF0000|zahigh;
	
	sim1.dspi3.mcr =0x81FF0000;//Starting Transfers
	while(((sim1.dspi3.sr & 0x0000F000)>>12)>0){}//Waiting for transfers to complete
	
        //reading POPR
        IMU_raw[0]=(short int)sim1.dspi3.popr;
	IMU_raw[1]=(short int)sim1.dspi3.popr;
	IMU_raw[2]=(short int)sim1.dspi3.popr;
        
        sim1.dspi3.mcr=0x81FF0C01;//Stop Transfers

}

In this case when I am reading the POPR register, the xahigh value is in IMU_raw[0] but IMU_raw[1] has zahigh value instead of yahigh and IMU_raw[2] is showing a '0' value. Then I replaced the above code with the following one.

Code: Select all

#define	xahigh 0x00001E00
#define	yahigh 0x00002200
#define	zahigh 0x00002600

void initIMUspi()
{
	J2[21].function(1);//SPI3 Input
	J2[22].function(1);//SPI3 Out
	J2[23].function(1);//SPI3 chip select 0
	J2[24].function(1);//SPI3 clock

	sim1.dspi3.ctar[0]=0x7E020006; //SPI Transfer protocol
}

void readIMU()
{
	sim1.dspi3.pushr=0x04FF0000|xahigh;
	sim1.dspi3.pushr=0x04FF0000|yahigh;
	sim1.dspi3.pushr=0x04FF0000|zahigh;
	sim1.dspi3.pushr=0x04FF0000|xahigh;
	sim1.dspi3.pushr=0x04FF0000|yahigh;
	sim1.dspi3.pushr=0x04FF0000|zahigh;

	sim1.dspi3.mcr =0x81FF0000;//Starting Transfers
	while(((sim1.dspi3.sr & 0x0000F000)>>12)>0){}//Waiting for transfers to complete
	
        //reading POPR
        IMU_raw[0]=(short int)sim1.dspi3.popr;
	IMU_raw[1]=(short int)sim1.dspi3.popr;
	IMU_raw[2]=(short int)sim1.dspi3.popr;
        IMU_raw[3]=(short int)sim1.dspi3.popr;
	IMU_raw[4]=(short int)sim1.dspi3.popr;
	IMU_raw[5]=(short int)sim1.dspi3.popr;
        
        sim1.dspi3.mcr=0x81FF0C01;//Stop Transfers

}
Now the first 3 entries of IMU_raw array are still messed up in the same way as before but IMU_raw[3],IMU_raw[4], IMU_raw[5] show the correct value corresponding to their command. I again modified the above code to include same sets of command again and still the first 3 entries are messed up but IMU_raw[3],IMU_raw[4], IMU_raw[5],IMU_raw[6],IMU_raw[7], IMU_raw[8] show the correct value. I am kind of confused,would like to know what other people faced while implementing QSPI on MOD54415. Also the transmission complete bit is set for each transfer or it is set when the entire contents of TX FIFO is shifted out? Using EOQ bit in PUSHR register to represent end of commands transmission, stops the receiving also and I end up with "0" in IMU_raw array.

Thanks in advance,
TM

Re: MOD54415 peculiar QSPI issue

Posted: Thu May 02, 2013 8:59 am
by dciliske
First of all, there is a driver for the DSPI module on the MOD54415. It has/can have the same interface as the QSPI driver from the other platforms. You will find it header file in 'nburn/MOD5441X/include' and an example on its use in 'nburn/examples/MOD5441X/DSPI2Serial'.

Now, if you knew about that already, and still want to do the low level implementation, let's examine your code and questions. You asked if the transfer complete flag will be set after each transfer or only after the full queue is shifted. It is set after every frame is shifted. What you're looking for is the "end of queue flag", which is only set after a frame with the EOQ bit set in its command section is shifted out. You'll want to set this bit when you add the last frame to the PUSHR register. To be honest, it sounds like someone isn't sending the right data during frame #2 (1, 2, 3...). Also, does the IMU require that the chip select be continuously asserted for the duration of the transactions? You are raising it between every transfer by not setting the CONT bit in the PUSHR register.

One small critique, comment or use defines for your register settings. I realize your at the rough prototype stage, but even now it will save you a lot of pain trying to decipher what your settings are. I know it does; I implemented our driver for this module. Also, even having implemented module, I have no idea what baudrate your trying to use.

Finally, you should see about using a logic analyzer to examine the data actually being sent across the bus.

Re: MOD54415 peculiar QSPI issue

Posted: Thu May 02, 2013 9:13 am
by pbreed
I have code for reading from a very similar IMU....
This code was not written for public consumption it was a quick hack to see if I could get data from the device....
I believe I still have this hardware set up at home and I can clean this up and send a better copy early next week...
(I've since switched to a MPU9150 based imu for my flying toys ;-))

Paul

I'm almost embarrassed to post this as it does not have a single comment....

The IMU is hooked up to the following NANO pins... (if your using a MOD54 then your pins will differ...
Pins[32].function(PIN_32_DSPI3_SIN);
Pins[34].function(PIN_34_DSPI3_SOUT);
Pins[36].function(PIN_36_DSPI3_PCS0);
Pins[38].function(PIN_38_DSPI3_SCK);
Pins[50].function(PIN_50_IRQ2);

/******************FIle SPI_imu.h ***************/
void IMUInit(int prio);
void StrShowImuRecord(char * st);


/*******************File SPI_imu.cpp************/
#include "predef.h"
#include <constants.h>
#include <sim5441X.h> /*on-chip register definitions*/
#include <ucos.h>
#include <pins.h>
#include <intcdefs.h>
#include <cfinter.h>
#include <utils.h>
#include <stdio.h>
#include "log.h"
#include "flags.h"
#include "SPI_Imu.h"
#include "PITSem.h"

#define IMU_SPI (sim1.dspi3)


#define SPI_TX_MASK (0x02000000)
#define SPI_RX_MASK (0x00020000)
#define SPI_FM_MASK (0x10000000)


#define IMU_PCS_MASK (0x00010000)

void IMUSendSpiTx(WORD v_to_send, int end)
{
IMU_SPI.sr=SPI_TX_MASK;

while((IMU_SPI.sr & SPI_TX_MASK)==0) asm(" nop");


if(end)
{
IMU_SPI.pushr=0x08000000+v_to_send+IMU_PCS_MASK;
}
else
{
IMU_SPI.pushr=0x80000000+v_to_send+IMU_PCS_MASK;
}

}




WORD IMUDoSpiRx()
{
DWORD dw1;
IMU_SPI.sr=SPI_RX_MASK;
asm(" nop");
dw1=IMU_SPI.sr;

while((dw1 & SPI_RX_MASK)==0)
{asm("nop");
dw1=IMU_SPI.sr;
}

return IMU_SPI.popr;
}



void IMUSpiStart()
{
IMU_SPI.sr=SPI_FM_MASK;
}


void IMUSpiFrameWait()
{
while (( IMU_SPI.sr & SPI_FM_MASK)==0) asm("nop");
}

void IMUQFlushSPIRX()
{
DWORD dw1;
DWORD dw;
IMU_SPI.sr=SPI_RX_MASK;
asm(" nop");
dw1=IMU_SPI.sr;

while(dw1 & SPI_RX_MASK)
{
dw=IMU_SPI.popr;
IMU_SPI.sr=0x00020000;

dw1=IMU_SPI.sr;
}
}

OS_SEM ImuFrameSem;
OS_SEM ImuTickSem;

volatile DWORD ImuTick;

//The IRQ2 line that indicates the IMU is ready with data
INTERRUPT(IMUTick,0x2700)
{
sim2.eport.epfr=4;
ImuTick++;
OSSemPost(&ImuTickSem);
}


INTERRUPT(IMU_ReadISR,0x2700)
{
IMU_SPI.sr=SPI_FM_MASK;
OSSemPost(&ImuFrameSem);
}


WORD ImuResults[13];
DWORD nImu;

void IMUTask(void * pd)
{

Pins[32].function(PIN_32_DSPI3_SIN);
Pins[34].function(PIN_34_DSPI3_SOUT);
Pins[36].function(PIN_36_DSPI3_PCS0);
Pins[38].function(PIN_38_DSPI3_SCK);
Pins[50].function(PIN_50_IRQ2);


IMU_SPI.mcr=0x80FF0000; //1 0 00 - 0 0 0 0 -1111 - 1111 - 0 0 0 0 0 0 0 0

IMU_SPI.ctar[0]= 0x7EFC1116; //0 111 - 1 1 1 0 - 11 11 - 11 00 - 0001 0001 0110

IMU_SPI.sr=SPI_FM_MASK;

IMU_SPI.rser=SPI_FM_MASK;//Turn off DMA requests



OSSemInit(&ImuFrameSem,0);
OSSemInit(&ImuTickSem,0);

SETUP_DSPI3_ISR(&IMU_ReadISR,3);
SETUP_IRQ2_EDGEPORT2_ISR(&IMUTick,2);

sim2.eport.eppar&=0xFFCF;
sim2.eport.eppar|=0x0010; //Positive edge trigger IRQ2
sim2.eport.epier|=4;
sim2.eport.epfr=4;

Pins[49].function(0);
Pins[49]=0;


while(1)
{
OSSemPend(&ImuTickSem,0); //Wait on the IRQ pin that says the IMU is ready
Pins[49]=1;

IMUSendSpiTx(0x3E00,0); //1
IMUSendSpiTx(0x0000,0); //2
IMUSendSpiTx(0x0000,0); //3
IMUSendSpiTx(0x0000,0); //4
IMUSendSpiTx(0x0000,0); //5
IMUSendSpiTx(0x0000,0); //6
IMUSendSpiTx(0x0000,0); //7
IMUSendSpiTx(0x0000,0); //8
IMUSendSpiTx(0x0000,0); //9
IMUSendSpiTx(0x0000,0); //10
IMUSendSpiTx(0x0000,0); //11
IMUSendSpiTx(0x0000,0); //12
IMUSendSpiTx(0x0000,1); //13
Pins[49]=0;
OSSemPend(&ImuFrameSem,0);

for(int i=0; i<13; i++) //Read the 13 registers from the SPI buffers into the ImuResults records....
ImuResults=IMUDoSpiRx();
nImu++;
OSFlagSet(&DataFlag,NEW_IMU);

}
}



void StrShowImuRecord(char * st)
{
char * cp=st;

for(int i=1; i<13; i++)
{
cp+=siprintf(cp,"%04X,",(ImuResults&0x3FFF)<<2);
}
DWORD s=Secs;
DWORD h=(s /3600);
DWORD m=(s/60)%60;
s=(s%60);

cp+=siprintf(cp," %ld : %ld %ld %02d:%02d:%02d\r\n",nImu/Secs,ImuTick/Secs,Pit_Count/Secs,h,m,s );

}




void IMUInit(int prio)
{
OSSimpleTaskCreatewName(IMUTask,prio,"IMU Task");
}

Re: MOD54415 peculiar QSPI issue

Posted: Thu May 02, 2013 9:15 am
by nicobari
Hi, Thanks for the reply. In fact I was planning to use QSPI driver but I read somewhere in the run time library document that higher level functions increases the computational overhead and since delay and speed is critical for my system (it includes other higher level functions and has a time dependent interrupt) I decided to go for low level implementation. I tried using EOQ for my last frame but whenever I did that reading POPR register returned only 0. I read the reference manual and just know that EOQ bit stops the transfer but no where it says that it flushes the RX FIFO, so I am kind of confused. Also I see now that you have mentioned, the signal diagram of IMU shows continuous assertion of chip select but it is not mentioned anywhere in the datasheet. Also thanks for the critique it is always helpful to get people's point of view. I will run some more tests and post the results.

Thanks again,
TM