Dear all:
I used QSPI on mcf52259 to connect mcp2515.My target is through CAN-bus communication with other nodes.Therefore i extend other CAN controller with SPI.The chip of mcf52259 has a QSPI to control SPI bus.I didn't know somethings when i read that manual.Here is questions
1.It has a CMD RAM of 16Bytes.Here is my operation(pseudo code)
QAR = 0x20
QDR = READ_CMD
QDR's size is 2Bytes, But CMD RAM only use 1Byte.And QCR is accessed using the upper byte of the QDR.Is it means the high(1Byte) of 2Bytes for QCR and low of 2Bytes for CMD RAM?
2. QSPI has 16 entries.Each entry has CMD RAM,TX RAM and RX RAM.Most slave devices receive CMD need pulling CS low.Therefore, i must pulling CS low or high when every entry execute before and after on transfer start. Is it correct?
Thanks
Kevin Chen
解決済! 解決策の投稿を見る。
I work on a product that has an MCF5329 with a QSPI connected to three MCP2515 chips. We also have an ADC on the same SPI bus.
So we have a lot of code handling CAN over the MCP2515's accessed via the QSPI.
CAN is hard enough to get right. The MCP2515 makes it a whole lot harder as it takes a (relatively) long time to read and write the registers and you have to get to them via an SPI device of some sort. The QSPI adds another layer of agony. It is very efficient, but also very complex. There are many man-months of code required to get this all working properly.
Our QSPI driver code takes 460 lines of code and comments. It consists of a "qspi_enqueue()" function that manages a software queue of commands. These are completed by interrupts that then call back queued completion routines.
Our MCP2515 driver code consists of 43 functions and 2110 lines of code and comments.
The ADC driver (running over the QSPI) takes 552 lines.
> QSPI has 16 entries.
QCRn[cont] controls the assertion of the chip select. QCRn[QSPI_CS] controls which chip select is asserted for a transfer. The QSPI handles the chip selects for you.
> QDR's size is 2Bytes, But CMD RAM only use 1Byte.And QCR is accessed
> using the upper byte of the QDR.Is it means the high(1Byte) of 2Bytes for
> QCR and low of 2Bytes for CMD RAM?
Just treat all RAM locations as 16 bits. The Command RAM doesn't use the lower byte, but just ignore that. Write from 1 to 16 16-bit-words into the command RAM via QDR. Then load 1 to 16 transmit data values to send. Then load up all the other registers and start the transfer. When it finishes (in final code, when it interrupts you), read the 1 to 16 receive data values and pass them back to whatever function wanted them.
Our code is particularly complex because we can have all three MCP2515's and the ADC all running at the same time and interleaving transfers, so there are queues and callback functions and all sorts of stuff. We're also running 8-bit SPI transfers to the MCP2515's and 16-bit transfers (with 6us conversion delays) to the ADC. If you've only got one MCP2515 you can probably write a simple function that just performs an "n-byte" QSPI single transfer and waits for it to finish. At a high enough SCI bit rate (MCP2515 can handle 10MHz) an 8 byte transfer should take less than 8us.
When in doubt, just ask Google:
http://lxr.free-electrons.com/source/drivers/spi/spi-coldfire-qspi.c
You should also type "qspi" into the Search Field at the top of this page. You'll find 29 previous posts, some of which may help you. Some of them probably list existing sample code and where to get it.
Tom
I work on a product that has an MCF5329 with a QSPI connected to three MCP2515 chips. We also have an ADC on the same SPI bus.
So we have a lot of code handling CAN over the MCP2515's accessed via the QSPI.
CAN is hard enough to get right. The MCP2515 makes it a whole lot harder as it takes a (relatively) long time to read and write the registers and you have to get to them via an SPI device of some sort. The QSPI adds another layer of agony. It is very efficient, but also very complex. There are many man-months of code required to get this all working properly.
Our QSPI driver code takes 460 lines of code and comments. It consists of a "qspi_enqueue()" function that manages a software queue of commands. These are completed by interrupts that then call back queued completion routines.
Our MCP2515 driver code consists of 43 functions and 2110 lines of code and comments.
The ADC driver (running over the QSPI) takes 552 lines.
> QSPI has 16 entries.
QCRn[cont] controls the assertion of the chip select. QCRn[QSPI_CS] controls which chip select is asserted for a transfer. The QSPI handles the chip selects for you.
> QDR's size is 2Bytes, But CMD RAM only use 1Byte.And QCR is accessed
> using the upper byte of the QDR.Is it means the high(1Byte) of 2Bytes for
> QCR and low of 2Bytes for CMD RAM?
Just treat all RAM locations as 16 bits. The Command RAM doesn't use the lower byte, but just ignore that. Write from 1 to 16 16-bit-words into the command RAM via QDR. Then load 1 to 16 transmit data values to send. Then load up all the other registers and start the transfer. When it finishes (in final code, when it interrupts you), read the 1 to 16 receive data values and pass them back to whatever function wanted them.
Our code is particularly complex because we can have all three MCP2515's and the ADC all running at the same time and interleaving transfers, so there are queues and callback functions and all sorts of stuff. We're also running 8-bit SPI transfers to the MCP2515's and 16-bit transfers (with 6us conversion delays) to the ADC. If you've only got one MCP2515 you can probably write a simple function that just performs an "n-byte" QSPI single transfer and waits for it to finish. At a high enough SCI bit rate (MCP2515 can handle 10MHz) an 8 byte transfer should take less than 8us.
When in doubt, just ask Google:
http://lxr.free-electrons.com/source/drivers/spi/spi-coldfire-qspi.c
You should also type "qspi" into the Search Field at the top of this page. You'll find 29 previous posts, some of which may help you. Some of them probably list existing sample code and where to get it.
Tom
Thank you for your response.
I have read manual in detail the.I work on product that has two mcp2515 chips.Now, i am writing some codes to test QSPI and mcp2515.Here are steps:
1.reset mcp2515
2.write value to CNF1 register of mcp2515
3.read value of CNF1 register
If the twice of value are same, QSPI and mcp2515 is right.I find some example code in MQX directories.So, i modify it for mcp2515.
These files are Qspi.h,Qspi.c,Qspi_example.c,Qspi_example.h,Qspi_main.c.
// init QSPI
MCF_QSPI_QMR = (MCF_QSPI_QMR_MSTR | ((0x0 & 0x3) <<8));// bits is default 16bits. baudrate is 10Mhz.(in other function)
MCF_QSPI_QWR = MCF_QSPI_QWR_CSIV;
// ready some data
tQSPIBuffers *MyBuf1;
tQSPIBuffers *MyBuf2;
tQSPIBuffers *MyBuf3;
MyBuf1->pu8CMD[0] = ((MCF_QSPI_QDR_CONT | MCF_QSPI_QDR_BITSE | MCF_QSPI_QDR_CS3) << 8);
MyBuf1->pu16TxData[0] = CAN_RESET;// reset instruction of mcp2515
MyBuf2->pu8CMD[0] = ((MCF_QSPI_QDR_CONT | MCF_QSPI_QDR_BITSE | MCF_QSPI_QDR_CS3) << 8);
MyBuf2->pu16TxData[0] = (CAN_WRITE << 8) | CNF1;
MyBuf2->pu16TxData[1] = (0x25 << 8) ;
MyBuf3->pu8CMD[0] = ((MCF_QSPI_QDR_CONT | MCF_QSPI_QDR_BITSE | MCF_QSPI_QDR_CS3) << 8);
MyBuf3->pu16TxData[0] = (CAN_READ << 8) | CNF1;
QSPIPollBufferTransfer(MyBuf1);
QSPIPollBufferTransfer(MyBuf2);
QSPIPollBufferTransfer(MyBuf3);
when i print struct MyBuf3, the twice of data wasn't same.Could you give me some advice on these codes?
Thanks
Kevin
You're doing the right thing with those buffers, but I can spot three obvious bugs.
> MCF_QSPI_QMR = (MCF_QSPI_QMR_MSTR | ((0x0 & 0x3) <<8)); // bits is default 16bits
For the MCP2515 you have to program the QSPI to generate EIGHT bit transfers. You're sending 16 bits in each command, which the MCP2515 will interpret as two 8-bit transfers. Set the "BITS" field to "8", which is 0x2000. This may be defined in your headers as "MCF_QSPI_QMR_BITS(n)". You can try and pack two bytes into 16 bits, but then you can't read or write an ODD number of bytes, and you'll need to do this with this chip.
> MyBuf2->pu16TxData[0] = (CAN_WRITE << 8) | CNF1;
I can't remember if SPI data is send high or low byte first when sending 16 bits. It doesn't matter. You should be sending 8 bit data a byte at a time. So you should be setting:
MyBuf2->pu16TxData[0] = CNF1;
MyBuf2->pu16TxData[1] = CAN_WRITE;
MyBuf2->pu16TxData[2] = 0x25;
> MyBuf2->pu8CMD[0] = ((MCF_QSPI_QDR_CONT | MCF_QSPI_QDR_BITSE | MCF_QSPI_QDR_CS3) << 8);
> MyBuf2->pu16TxData[0] = (CAN_WRITE << 8) | CNF1;
> MyBuf2->pu16TxData[1] = (0x25 << 8) ;
The bug there is that if you're sending TWO data words, you also need to send TWO command words as well. For every data byte that is sent it has to have a matching command word. So for my example above sending three bytes you have to fill in pu8CMD[0], pu8CMD[1] and pu8CMD[2]. You fill them all in with the same values.
In fact since you're always sending the same command data, load up all 16 of them once, and then you never have to load them again. Except you have two MCP2515's so you want two sets of commands, one for each chip-select.
QSPIPollBufferTransfer(MyBuf1);
Either in the function call or in the "MyBuf" structure you have to tell the QSPI (in QWR[ENDQP]) how many bytes you're sending, because different commands need different numbers of data bytes. In my code this is:
MCF_QSPI_QWR = MCF_QSPI_QWR_CSIV | MCF_QSPI_QWR_ENDQP(p->num - 1);
> tQSPIBuffers *MyBuf1;
> tQSPIBuffers *MyBuf2;
> tQSPIBuffers *MyBuf3;
I hope you've left a lot of code out in your example as in what you showed those pointers aren't initialized. For test code I'd expect then not to be pointers, but to be:
tQSPIBuffers MyBuf1;
tQSPIBuffers MyBuf2;
tQSPIBuffers MyBuf3;
Tom
Thank you very much!
Here, i have fix three bugs.But i can't get correct data.Next is my changes:
1.bits of transfer.
I setting bits of transfer is 8bits.In my code, the buffer of struct tQSPIBuffers is 16bits.And QSPI transfer type is MSB firstly.So, I do this
typedef struct tQSPIBuffers{
uint8 u8Size;
uint16 *pu16TxData;
uint16 *pu16RxData;
uint8 *pu8Cmd;
uint8 u8stat;
}tQSPIBuffers;
// after init buffer
MyBuf1->pu8Cmd[0] = MCF_QSPI_QDR_CONT | MCF_QSPI_QDR_BITSE | MCF_QSPI_QDR_CS3;
MyBuf1->pu16TxData[0] = (CAN_RESET << 8);
MyBuf2->pu8Cmd[0] = MCF_QSPI_QDR_CONT | MCF_QSPI_QDR_BITSE | MCF_QSPI_QDR_CS3;
MyBuf2->pu8Cmd[1] = MCF_QSPI_QDR_CONT | MCF_QSPI_QDR_BITSE | MCF_QSPI_QDR_CS3;
MyBuf2->pu8Cmd[1] = MCF_QSPI_QDR_CONT | MCF_QSPI_QDR_BITSE | MCF_QSPI_QDR_CS3;
MyBuf2->pu16TxData[0] = (CAN_WRITE << 8);
MyBuf2->pu16TxData[1] = (CNF1 << 8);
MyBuf2->pu16TxData[2] = (0x26 << 8);
// cmd of MyBuf3 is same to previous
MyBuf3->pu16TxData[0] = (CAN_WRITE << 8);
MyBuf3->pu16TxData[1] = (CNF1 << 8);
Here, i have a question.The QDR and buffer(tx/rx) of struct tQSPIBuffers has 16bits, while i choose 8bits to transfer for each entry.In this case, each entry of transfer has tx/rx 8bits on 8bits(MSB) of 16bits.If it is right, i think shifleft 8bits is needed.Is this right?
2. polltransferbuffer function
static int8 QSPIPollBufferTransfer_NoWrap(tQSPIBuffers *sQSPIBuff)
{
uint8 j;
set_cs(0);
for (j=0; j < sQSPIBuff->u8Size; j++){
MCF_QSPI_QAR = QSPI_COMMAND_ADDRESS+j;
MCF_QSPI_QDR = MCF_QSPI_QDR_DATA(sQSPIBuff->pu8Cmd[j]);
MCF_QSPI_QAR = QSPI_TRANSMIT_ADDRESS+j;
MCF_QSPI_QDR = sQSPIBuff->pu16TxData[j];
}
MCF_QSPI_QWR = (MCF_QSPI_QWR & MCF_QSPI_QWR_CSIV) |
MCF_QSPI_QWR_ENDQP((sQSPIBuff->u8Size)-1) |
MCF_QSPI_QWR_NEWQP(0);
MCF_QSPI_QDLYR |= MCF_QSPI_QDLYR_SPE;
while (!(MCF_QSPI_QIR & MCF_QSPI_QIR_SPIF))
;
MCF_QSPI_QIR |= MCF_QSPI_QIR_SPIF;
MCF_QSPI_QAR = QSPI_RECEIVE_ADDRESS;
for (j=0; j < sQSPIBuff->u8Size; j++){
sQSPIBuff->pu16RxData[j] = MCF_QSPI_QDR;
}
set_cs(1);
return 0;
}
I have a doubt that code of receiver.For example, i use READ instruction and send two bytes data(instruction and address).Now, mcp2515 has receiving these data and put some data to SDO line on address. I think these data will put to last entry of receive buffer at current transfer queue.So, that last loop could be drop.
sQSPIBuff->pu16RxData[sQSPIBuff->u8Size] = MCF_QSPI_QDR;
Kevin
I gave the following example:
MyBuf2->pu16TxData[0] = CNF1;
MyBuf2->pu16TxData[1] = CAN_WRITE;
MyBuf2->pu16TxData[2] = 0x25;
You did this:
MyBuf2->pu16TxData[0] = (CAN_WRITE << 8);
MyBuf2->pu16TxData[1] = (CNF1 << 8);
MyBuf2->pu16TxData[2] = (0x26 << 8);
I provided you with working code in my example. Those shifts are wrong. My manual on the QSPI states:
30.4.1.2 Transmit RAM
... Outbound data must be written to transmit RAM in a
right-justified format. The unused bits are ignored.
You pushed the 8 bit data to the LEFT. It does not need this at all.
> i think shifleft 8bits is needed.Is this right?
You should read the entire QSPI chapter again. That information is in there (in my copy, it should be in yours too). If it isn't in yours, download and read other Coldfire manuals that have QSPIs. Sometimes some manuals are better than others, but most times the chapters on the same peripherals are cut-and-paste identical.
I won't go through the rest of your code, there are too many problems. Rip it up and start again. I would suggest only using one buffer. Fill it in, send a command, fill it in again for the next command, send that an so on.
> // after init buffer
If I can't see the "init buffer" code I can't check to see if it is OK.
> for (j=0; j < sQSPIBuff->u8Size; j++){
There's no code initialising "u8Size". It has to be set to "1" for the first command and "3" for the second one, and so on for commands of different lengths (lengths from 1 to 9 are required).
I would STRONGLY recommend that you connect an oscilloscope to the SPI bus. Then check that the data that you think is going onto the bus is what is actually getting on the bus. If you had done this with your current code you'd have seen that you're always sending zeroes. You can also see what data is being read back from the chip
> set_cs(0);
Don't you have the QSPI CS pins connected to the SPI peripherals? You seem to as you're adding "MCF_QSPI_QDR_CS3" to the command which will drive that chip select during the transfer. So why are you calling a different "set_cs(0)" function?
You're sending (or trying to send) three bytes, but are never setting "pu8Cmd[2]" to anything. The number of commands must match the number of data bytes. And if you're reading data, the number of command bytes must match the whole transfer length (write and read part).
The third command buffer is WRITING to the chip, but you're never sending a READ command to try and read anything back from the chip. Your last paragraph mentions sending a READ. What happens is that you have to send the READ as two bytes (as you say), but you then have to send a THIRD byte (content doesn't matter) to read the data back. The read data will be in the THIRD byte in the read buffer. To read back a whole 8 byte message you have to send a "READ RX BUFFER" instruction and then perform another 8 transfers to get the data read back.
For the READ you should look at this on an oscilloscope and match it with the "FIGURE 12-2: READ INSTRUCTION" diagram in the MCP2515 manual. That shows the instruction, address and the returned data in the next 8 bits.
Like I said, expect this to take weeks or months.
If you don't need the QSPI speed, it might be easier if you can find some working MCP2515 code that uses "bit-bang" SPI and then just drive the SPI pins from software. You want to copy working MCP2515 code and not write it yourself.
Once you have that working you can then convert the SPI functions to ones using the QSPI. It is a lot easier to incrementally modify and improve working code than to write everything from scratch and then have to debug bugs in everything at the same time.
Tom
Thanks again.
Last time, that's my mistakes.I drop that and rewrite all code.I have upload my code in attach files.I also use oscilloscope to watch DIN,DOUT,SCK.Though i just got changes from high to low level.May be my range of oscilloscope too small.
My board has two mcp2515, one is connect CS3, other connect AD6(GPIO).That's why i use set_cs() function to control chip select line.These code i try to control first mcp2515 that use CS3 line as chip select.
Thanks
Kevin
> Though i just got changes from high to low level.
Why, what were you expecting to see?
Tom
I always got 0xff when i run these code.I try to use line short DIO with DOUT pin, and recv data is same as send.This means i send data, but mcp2515 doesn't recv for me a data.
> > Though i just got changes from high to low level.
> > May be my range of oscilloscope too small.
> Why, what were you expecting to see?
From what you said I thought you might have been expecting to see analog voltages. I don't see how you could blame the oscilloscope if you are seeing voltage level changes on it. You should measure the actual voltage swings on the oscilloscope and check they are the expected values. Note the CPU output voltages are probably 3.3V and so should the MCP2515, assuming you have it powered from 3.3V and not 5.0V.
> This means i send data, but mcp2515 doesn't recv for me a data.
That means you're sending the wrong data. Or the wrong chip select. Or have the wrong phasing between the chip-select, clock and data signals. Or the wrong delays.
The Chip Select has to go down first, then the first data bit needs to be driven, and then the clock goes from low to high. The CS-to-clock minimum time is 50ns. the data-to-clock minimum is 10ns and the data has to hold for at least 10ns after the clock.
If you look at the MCP2515 Data Sheet in the sections "FIGURE 12-10: SPI INPUT TIMING" and "TABLE 13-6: SPI INTERFACE AC CHARACTERISTICS" it shows you all the required timings.
You should check all the signals on the oscilloscope and make sure you're obeying the MCP2515's requirements. You may have the clock upside-down or something. You should MANUALLY DECODE (on paper) the signals that you are sending and match them with what you think you're sending. Compare with the diagrams in the MCP2515 manual.
Check CPOL, CPHA, QCD, CSIV again.
After you get that right you should be able to send a command to the MCP2515 and then on the oscilloscope, see data coming back. You decode what it is on the oscilloscope and then check the published timing with what you see, and then check that against the specified inbound-data timing on the CPU. Then you can check the data that is coming back in the registers against what you've manually decoded.
All of the above is a normal part of Electrical Engineering, design verification and embedded programming.
Are you remembering that the returned data is going to be in the THIRD Read RAM location and not the first?
Tom
:smileylaugh:I know why mcp2515 doesn't communication.It's cause time delay.
Thanks very much for help me solve these problems.
I am a newer of EE.You says right, and i must learn more about EE.Your advises are more helpful.:smileyhappy:
Kevin