Ethernet on T3.6 SPI1 with FIFO

Status
Not open for further replies.

alex-arc

Active member
i am trying to use a Wiz850io with the T3.6 but on SPI1
i think i have changed all the things that need changing but it gets stuck in the right in the beginning when tying to read the chip type.
it seems to be this while loop in the SPIFIFO that never reaches completion :confused:
line 382 in SPIFIFO.h
Code:
inline void write(uint32_t b, uint32_t cont=0) __attribute__((always_inline)) {
  uint32_t pcsbits = pcs1 << 16;
  if (pcsbits) {
    KINETISK_SPI1.PUSHR = (b & 0xFF) | pcsbits | (cont ? SPI_PUSHR_CONT : 0);
    while (((KINETISK_SPI1.SR) & (15 << 12)) > (3 << 12)) ; // wait if FIFO full
  } else {
    *reg1 = 0;
    KINETISK_SPI1.SR = SPI_SR_EOQF;
    KINETISK_SPI1.PUSHR = (b & 0xFF) | (cont ? 0 : SPI_PUSHR_EOQ);
    if (cont) {
      while (((KINETISK_SPI1.SR) & (15 << 12)) > (3 << 12)) ;
    } else {
      while (!(KINETISK_SPI1.SR & SPI_SR_EOQF)){
        //------------remove this------------------------
        digitalWrite(13,HIGH);
        delay(200);
        digitalWrite(13,LOW);
        delay(200);
        //------------------------------------
      }
      *reg1 = 1;
    }
  }
}

any ideas is greatly appreciated :)

the all the changes i have made to the Ethernet an core libs are here:
https://github.com/alex-Arc/cores/tree/SPI1FIFO
https://github.com/alex-Arc/Ethernet/tree/Alternet_SPI_pin
 
Last edited:
It may not be the problem, but only SPI0 has a FIFO of depth 4. SPI1 and SPI2 have depth-1 FIFO
 
It may not be the problem, but only SPI0 has a FIFO of depth 4. SPI1 and SPI2 have depth-1 FIFO

yes that is some of it

Code:
while (((KINETISK_SPI1.SR) & (15 << 12)) > (3 << 12)) ; // wait if FIFO full
should be
Code:
while (((KINETISK_SPI1.SR) & (15 << 12)) > ((1-1) << 12)) ; // wait if FIFO full
thanks to KurtE https://forum.pjrc.com/threads/45321-SPI-files-libraries-SPI-SPIN-SPIFIFO?highlight=SPI1

it stile doesn't work.
i am trying with out the FIFO function and that doesn't work either so i must have done something very wrong
Code:
// #include "SPIFIFO.h"
// #ifdef  HAS_SPIFIFO
// #define USE_SPIFIFO
// #endif
 
That was one of the first things I ran into with SPI1/2 when testing on T3.6, which is why I have the SPIN library (github/kurte), which has the full checking and the like.

But sometimes that is not enough. You have to carefully go through the logic, in certain cases. Ran into issue with ILI9341 library for reading pixels. Would do something like: PUSHR, PUSHR, PUSHR and then expect to have 3 bytes on the POPR to get the color...
So from your above:
Code:
inline void write(uint32_t b, uint32_t cont=0) __attribute__((always_inline)) {
  uint32_t pcsbits = pcs1 << 16;
  if (pcsbits) {
    KINETISK_SPI1.PUSHR = (b & 0xFF) | pcsbits | (cont ? SPI_PUSHR_CONT : 0);
   [COLOR="#FF0000"] while (((KINETISK_SPI1.SR) & (15 << 12)) > (3 << 12)) ; // wait if FIFO full[/COLOR]
  } else {
    *reg1 = 0;
    KINETISK_SPI1.SR = SPI_SR_EOQF;
    KINETISK_SPI1.PUSHR = (b & 0xFF) | (cont ? 0 : SPI_PUSHR_EOQ);
    if (cont) {
     [COLOR="#FF0000"] while (((KINETISK_SPI1.SR) & (15 << 12)) > (3 << 12)) ;[/COLOR]
    } else {
      while (!(KINETISK_SPI1.SR & SPI_SR_EOQF)){
        //------------remove this------------------------
        digitalWrite(13,HIGH);
        delay(200);
        digitalWrite(13,LOW);
        delay(200);
        //------------------------------------
      }
      *reg1 = 1;
    }
  }
}
Not sure what your pcs1 is?

You say it hangs, but maybe hard to say without seeing how this is called. That is are you passing in in cont?

You might want to take a look at my ili9341_t3n library and how it uses my SPIN...
In particular I have simple helper functions like:
Code:
#ifdef KINETISK	
	void writecommand_cont(uint8_t c) __attribute__((always_inline)) {
		_pkinetisk_spi->PUSHR = c | (pcs_command << 16) | SPI_PUSHR_CTAS(0) | SPI_PUSHR_CONT;
		_pspin->waitFifoNotFull();
	}
	void writedata8_cont(uint8_t c) __attribute__((always_inline)) {
		_pkinetisk_spi->PUSHR = c | (pcs_data << 16) | SPI_PUSHR_CTAS(0) | SPI_PUSHR_CONT;
		_pspin->waitFifoNotFull();
	}
	void writedata16_cont(uint16_t d) __attribute__((always_inline)) {
		_pkinetisk_spi->PUSHR = d | (pcs_data << 16) | SPI_PUSHR_CTAS(1) | SPI_PUSHR_CONT;
		_pspin->waitFifoNotFull();
	}
	void writecommand_last(uint8_t c) __attribute__((always_inline)) {
		uint32_t mcr = _pkinetisk_spi->MCR;
		_pkinetisk_spi->PUSHR = c | (pcs_command << 16) | SPI_PUSHR_CTAS(0) | SPI_PUSHR_EOQ;
		_pspin->waitTransmitComplete(mcr);
	}
	void writedata8_last(uint8_t c) __attribute__((always_inline)) {
		uint32_t mcr = _pkinetisk_spi->MCR;
		_pkinetisk_spi->PUSHR = c | (pcs_data << 16) | SPI_PUSHR_CTAS(0) | SPI_PUSHR_EOQ;
		_pspin->waitTransmitComplete(mcr);
	}
	void writedata16_last(uint16_t d) __attribute__((always_inline)) {
		uint32_t mcr = _pkinetisk_spi->MCR;
		_pkinetisk_spi->PUSHR = d | (pcs_data << 16) | SPI_PUSHR_CTAS(1) | SPI_PUSHR_EOQ;
		_pspin->waitTransmitComplete(mcr);
	}
#endif
But this has the added stuff of controlling the chip select pin(s). In my case the library makes sure the DC is on a hardware CS pin... And optionally CS can also be hardware CS (but not necessary). That is why here we have functions that are different for data versus command.

And from SPIN:
Code:
#if defined(KINETISK)
void SPINClass::waitFifoNotFull(void) {
    uint32_t sr;
    uint32_t tmp __attribute__((unused));
    do {
        sr = port().SR;
        if (sr & 0xF0) tmp = port().POPR;  // drain RX FIFO
    } while ((uint32_t)(sr & (15 << 12)) > (uint32_t)((_fifo_size-1) << 12));
}
void SPINClass::waitFifoEmpty(void) {
    uint32_t sr;
    uint32_t tmp __attribute__((unused));
    do {
        sr = port().SR;
        if (sr & 0xF0) tmp = port().POPR;  // drain RX FIFO
    } while ((sr & 0xF0F0) > 0);             // wait both RX & TX empty
}
void SPINClass::waitTransmitComplete(void)  {
    uint32_t tmp __attribute__((unused));
    while (!(port().SR & SPI_SR_TCF)) ; // wait until final output done
    tmp = port().POPR;                  // drain the final RX FIFO word
}
void SPINClass::waitTransmitComplete(uint32_t mcr) {
    uint32_t tmp __attribute__((unused));
    while (1) {
        uint32_t sr = port().SR;
        if (sr & SPI_SR_EOQF) break;  // wait for last transmit
        if (sr &  0xF0) tmp = port().POPR;
    }
    port().SR = SPI_SR_EOQF;
    port().MCR = mcr;
    while (port().SR & 0xF0) {
        tmp = port().POPR;
    }
}
Note my spin objects know the fifo size... Also they are holding onto a pointer to registers for SPI...
Hopefully from this you can pick and choose what you need to get yours to work.
 
Thanks KurtE.
after fixing the stuff in Ethernet and Socket i still cant get it to work.
SPIFIFO1 is mostly a clone of SPIFIFO (i was hoping for a quick fix) and looking at it, it looks like i will have to do with out FIFO or free up alternate pins for SPI0 or i wont make it to my deadline
 
We are trying to use a WIZ820io with a Teensy 3.6 on SPI2 (SPI0 is being used with LTC2983 temperature measurement system) and have run into the problems described above. Alex, from your last post is sounds like you got things working, is that correct? Do you mind sharing what all you needed to change, as we will need to change it again to use SPI2 as opposed to SPI1.

Thanks!
 
Status
Not open for further replies.
Back
Top