while(1) { vuint16 qdlyr=MCF_QSPI_QDLYR; if( (qdlyr & MCF_QSPI_QDLYR_SPE >> 0xF)==0) break; }
while (!(MCF_QSPI_QIR & MCF_QSPI_QIR_SPIF)) ; //wait for queue to end
void SPI_Flash_ReadStatusReg(void){ int i; spi_word_t rcv[16]; // QSPI Module Command RAM Registers (QCR0-QCR15) #define SPI_CMD_CS_ASRT 0xC0E0 //chip select 0 Active Low // Load Command: Set queue address (QAR) to COMMAND address [0x20 - 0x2F] MCF_QSPI_QAR = MCF_QSPI_QAR_CMD; // Write the command words MCF_QSPI_QDR = (uint16)(SPI_CMD_CS_ASRT); // Write Tx Data: Set queue address (QAR) to Transmit address [0x00 - 0x0F] MCF_QSPI_QAR = MCF_QSPI_QAR_TRANS; // Load the data to transmit MCF_QSPI_QDR = RDSR; //read status register (i,e. RDSR=0x05) /* Determine the active level, the first and last index of the transmit queue */ MCF_QSPI_QWR = (0 | (MCF_QSPI_QWR & MCF_QSPI_QWR_CSIV) | MCF_QSPI_QWR_NEWQP(0) | MCF_QSPI_QWR_ENDQP(1)); /* begin transfer */ MCF_QSPI_QDLYR |= MCF_QSPI_QDLYR_SPE; /* When transfer queue ends, QIR[SPIF] is set */ while (!(MCF_QSPI_QIR & MCF_QSPI_QIR_SPIF)) ; //wait for queue to end /* Set RAM address pointer to received data */ MCF_QSPI_QAR = MCF_QSPI_QAR_RECV; /* read received data from the RAM */ for (i = 0; i < 16; ++i) { rcv[i] = MCF_QSPI_QDR; } /* done */}
1) When chip select is asserted, QSPI_Din is toggling.
2) Why is the clock being interrupted in the middle of the sequence?
1.)I'm not sure why that is occuring, but if it becomes a problem you can add a delay between the assertion of the CS and the beginning of the clock. QDLYR[QCD], enabled in QCR[DSCK]
SVC2 wrote:
I am noticing 2 weird things:1) When chip select is asserted, QSPI_Din is toggling.
2) Why is the clock being interrupted in the middle of the sequence?
Standard delay after transfer = 17 / fsyswhen DT = 0.
Hi,
I’m trying to control a SPI flash using the QSPI in 5282.
It works well when send/received data is less that queue size.
It is a nighmare when data is more than queue size (for example to read/write 256 data into flash).
I am trying to use it in wraparound mode, but I don't have a way to synchronize the device and the code running in the processor.
bool_t qspi_tx_cont(const uint16 cmd, const uint16 *tx_buf, const uint16 tx_size, Bsp_QSPI_err_t *err) { const uint16 end_qp=(uint16) (tx_size > QSPI_QUEUE_LENGTH — QSPI_QUEUE_LENGTH : tx_size); uint32 count=0; uint16 i=0; // Fill the commands MCF_QSPI_QAR = MCF_QSPI_QAR_CMD; for(i=0; i < QSPI_QUEUE_LENGTH; ++i) MCF_QSPI_QDR = cmd; //0xCE00; // Determine the active level, the first and last index of the transmit queue MCF_QSPI_QWR = (unsigned short)(0 | (MCF_QSPI_QWR & MCF_QSPI_QWR_CSIV) | MCF_QSPI_QWR_WREN // Wrap enabled | MCF_QSPI_QWR_NEWQP(0) | MCF_QSPI_QWR_ENDQP(end_qp - 1) ); // Clear the error flags MCF_QSPI_QIR &= ~MCF_QSPI_QIR_WCEF;// Clear collision detected flag MCF_QSPI_QIR &= ~MCF_QSPI_QIR_ABRT;// Clear Abort flag // Fill Tx data MCF_QSPI_QAR = MCF_QSPI_QAR_TRANS; for(i=0; i < QSPI_QUEUE_LENGTH; ++i) { if(i < tx_size) MCF_QSPI_QDR = tx_buf[i]; else MCF_QSPI_QDR = 0; // dummy } // begin transfer in wrap around mode MCF_QSPI_QDLYR |= MCF_QSPI_QDLYR_SPE; // Send the rest while(i < tx_size) { // Fill Tx data MCF_QSPI_QAR = (uint16) (MCF_QSPI_QAR_TRANS + (i% QSPI_QUEUE_LENGTH)); MCF_QSPI_QDR = tx_buf[i]; // Next i++; } // Stop wrap around MCF_QSPI_QWR &= (~MCF_QSPI_QWR_WREN); // Wait for transfer complete // When transfer queue ends, QIR[SPIF] is set count=0; while (! (MCF_QSPI_QIR & MCF_QSPI_QIR_SPIF)) { if(count++ > QSPI_TRANSFER_TIMEOUT) { if(err) *err = BSP_QSPI_TRANSFER_TIMEOUT; return FALSE; } } // SPE automatically clears when transfer is complete if( MCF_QSPI_QDLYR & MCF_QSPI_QDLYR_SPE ) { if(err) *err = BSP_QSPI_SPE_NOT_ASSERTED; return FALSE; } // clear the SPIF flag MCF_QSPI_QIR |= MCF_QSPI_QIR_SPIF; // check if a write collision error has occured if(MCF_QSPI_QIR & MCF_QSPI_QIR_WCEF) { if(err) *err = BSP_QSPI_COLLISION; return FALSE; } // check for if an abort error has occured else if(MCF_QSPI_QIR & MCF_QSPI_QIR_ABRT) { if(err) *err = BSP_QSPI_ABORTED; return FALSE; } // done return TRUE; }
Any hints?
Thanks,
S.
// perform both output and input qspi i/ovoidqspi_transfer(byte *buffer, int length){#if MCF52221 || MCF52233 || MCF52259 int i; int x; int request; x = splx(7); // while there is data remaining... while (length) { // process up to 16 bytes at a time request = MIN(length, 16); // for all bytes... for (i = 0; i < request; i++) { // set up the command MCF_QSPI_QAR = MCF_QSPI_QAR_CMD+i; MCF_QSPI_QDR = MCF_QSPI_QDR_CONT|(csiv?0:MCF_QSPI_QDR_QSPI_CS0); // copy tx data to qspi ram MCF_QSPI_QAR = MCF_QSPI_QAR_TRANS+i; MCF_QSPI_QDR = buffer[i]; } // set the queue pointers assert(request); MCF_QSPI_QWR = (csiv?0:MCF_QSPI_QWR_CSIV)|MCF_QSPI_QWR_ENDQP(request-1)|MCF_QSPI_QWR_NEWQP(0); // start the transfer MCF_QSPI_QDLYR = MCF_QSPI_QDLYR_SPE; // wait for transfer complete assert(! (MCF_QSPI_QIR & MCF_QSPI_QIR_SPIF)); while (! (MCF_QSPI_QIR & MCF_QSPI_QIR_SPIF)) { } MCF_QSPI_QIR = MCF_QSPI_QIR_SPIF; assert((MCF_QSPI_QWR & 0xf0) >> 4 == request-1); assert(! (MCF_QSPI_QDLYR & MCF_QSPI_QDLYR_SPE)); // for all bytes... for (i = 0; i < request; i++) { // copy rx data from qspi ram MCF_QSPI_QAR = MCF_QSPI_QAR_RECV+i; buffer[i] = MCF_QSPI_QDR; } buffer += request; length -= request; } // transfer complete MCF_QSPI_QWR = csiv?MCF_QSPI_QWR_CSIV:0; splx(x);#elif MCF51JM128 // cs active if (csiv) { PTED &= ~PTEDD_PTEDD7_MASK; } else { PTED |= PTEDD_PTEDD7_MASK; } while (length) { // N.B. spi needs us to read the status register even for release code! ASSERT(SPI1S & SPI1S_SPTEF_MASK); ASSERT(! (SPI1S & SPI1S_SPRF_MASK)); SPI1DL = *buffer; while (! (SPI1S & SPI1S_SPTEF_MASK)) { // NULL } while (! (SPI1S & SPI1S_SPRF_MASK)) { // NULL } *buffer = SPI1DL; buffer++; length--; } // cs inactive if (csiv) { PTED |= PTEDD_PTEDD7_MASK; } else { PTED &= ~PTEDD_PTEDD7_MASK; }#endif}
Hi Rich,
Where do i can get your zip code. Right now iam trying to work on M52233 MCU but could not get the result.
// perform both output and input qspi i/ovoid qspi_transfer(uint16 *buffer, int length){ int i; int x; int request; // x = splx(7); // while there is data remaining... while (length) { // process up to 16 bytes at a time request = QSPI_MIN(length, 16); // for all bytes... for (i = 0; i < request; i++) { // set up the command MCF_QSPI_QAR = MCF_QSPI_QAR_CMD+i; MCF_QSPI_QDR = 0xCE00; // copy tx data to qspi ram MCF_QSPI_QAR = MCF_QSPI_QAR_TRANS+i; MCF_QSPI_QDR = buffer[i]; } // set the queue pointers assert(request); MCF_QSPI_QWR = (MCF_QSPI_QWR_CSIV| MCF_QSPI_QWR_ENDQP(request-1)| MCF_QSPI_QWR_NEWQP(0)); // start the transfer MCF_QSPI_QDLYR = MCF_QSPI_QDLYR_SPE; // wait for transfer complete assert(! (MCF_QSPI_QIR & MCF_QSPI_QIR_SPIF)); while (! (MCF_QSPI_QIR & MCF_QSPI_QIR_SPIF)) { } MCF_QSPI_QIR = MCF_QSPI_QIR_SPIF; assert((MCF_QSPI_QWR & 0xf0) >> 4 == request-1); assert(! (MCF_QSPI_QDLYR & MCF_QSPI_QDLYR_SPE)); // for all bytes... for (i = 0; i < request; i++) { // copy rx data from qspi ram MCF_QSPI_QAR = MCF_QSPI_QAR_RECV+i; buffer[i] = MCF_QSPI_QDR; } buffer += request; length -= request; } // transfer complete MCF_QSPI_QWR = csiv—MCF_QSPI_QWR_CSIV:0; // splx(x);}
Should there be any delay after I initialize the QSPI registers and start using it?
When I trace step through the code, it works. Nevertheless, when I run it, it does not work.
Thanks,
Simon
The only delay I have been aware of is after I reset the target chip, it some time before it will properly respond to flash commands. I do not believe the local qspi needs any time.
Wow, it looks like we have a new web interface here, and spell check!
Hi,
Now I am adding more devices in different chip selects. I notice that when the code
MCF_QSPI_QWR = (unsigned short) (
((cs_active_lvl == SPI_CS_ACTIVE_LO) ? 0: MCF_QSPI_QWR_CSIV) |
MCF_QSPI_QWR_ENDQP(request-1) |
MCF_QSPI_QWR_NEWQP(0));
is executed, ALL 4 chips selects are getting asserted (driven Low).
Is there a way to assert solely the desired CS?
Note that the command I enter is:
MCF_QSPI_QAR = (uint16)(MCF_QSPI_QAR_CMD+i);MCF_QSPI_QDR = (uint16)(MCF_QSPI_QDR_CONT | MCF_QSPI_QDR_BITSE | active_level);
where
active_level= cs_active_lvl == SPI_CS_ACTIVE_LO ? ((~chip_select)&0xF00) : chip_select;// chip_select variable is set as // MCF_QSPI_QDR_QSPI_CS3 or MCF_QSPI_QDR_QSPI_CS2,..//// Note:// MCF_QSPI_QDR_QSPI_CS3= 0x800 => ~0x800 & 0xF00 = 0x700// MCF_QSPI_QDR_QSPI_CS2= 0x400 => ~0x400 & 0xF00 = 0xB00// MCF_QSPI_QDR_QSPI_CS1= 0x200 => ~0x200 & 0xF00 = 0xD00// MCF_QSPI_QDR_QSPI_CS0= 0x100 => ~0x100 & 0xF00 = 0xE00//
Thanks,
Simon
The QWR controls the "inactive" level of the CS -- i.e., the level of all 4 lines while you are not driving a transfer. During the transfer, you control the "active" chip selects individually with the 4 bits in the command register.
Typically, you'll want the "inactive" level to be 1, so you should set bit 12 of QWR to 1. Then you will want to set the appropriate CS line low in the command register -- typically only one of bits 8 thru 11 of QCRx will be 0 at a time unless you are using an external decoder.
> Is there a way to assert solely the desired CS?
Yes, by setting just that desired CS to 0 (assuming active low) in QCRx, and all of the other CS to 1.
Rich,
In the example you sent me, you have:
while(length)
{
// process up to 16 bytes at a time
request = MIN(length, 16);
// for all bytes...
for (i = 0; i < request; i++)
{
// set up the command
MCF_QSPI_QAR = MCF_QSPI_QAR_CMD+i;
MCF_QSPI_QDR = MCF_QSPI_QDR_CONT;
// copy tx data to qspi ram
MCF_QSPI_QAR = MCF_QSPI_QAR_TRANS+i;
MCF_QSPI_QDR = buffer[i];
}
// set the queue pointers
assert(request);
MCF_QSPI_QWR = (csiv?0:MCF_QSPI_QWR_CSIV) |
MCF_QSPI_QWR_ENDQP(request-1) |
MCF_QSPI_QWR_NEWQP(0);
//...
With csiv set to 1, QWR is being set to 0, thus ALL 4 chip selects going Low.
Simon
That's correct -- thats the *inactive* value that is used when you want no chips selected, so all lines should be the same. You probably want that to be "1".
Then, when you have chips selected, you need to put the proper bitmask in here in the command registers:
// for all bytes...
for (i = 0; i < request; i++) {
// set up the command
MCF_QSPI_QAR = MCF_QSPI_QAR_CMD+i;
MCF_QSPI_QDR = MCF_QSPI_QDR_CONT|(csiv?0:MCF_QSPI_QDR_QSPI_CS0);
// copy tx data to qspi ram
MCF_QSPI_QAR = MCF_QSPI_QAR_TRANS+i;
MCF_QSPI_QDR = buffer[i];
}
You want to change the CS0 term to be the appropriate bitmask.