i-MX7 - Chip Select Signal behavior with SS_CTL

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

i-MX7 - Chip Select Signal behavior with SS_CTL

2,915 Views
einarikoivu
Contributor I

I'm trying to implement a driver for an SPI peripheral. The code would be executed in M4. I'm using the Sabre board Rev B

The peripheral requires the data in a format of 9-bit words, the first bit is a control bit followed by eight data bits. The Chip Select signal must be active diring the whole data transfer.

For that, I need to have burst length of 9 bits. (BURST_LENGTH = 8). The behavior of the Chip Select should be controlled by SS_CTL. My problem is that SS_CTL has no effect on the behavior of the Chip Select.

I have set SMC (Start Mode Control) to zero, as suggested by the reference manual. After that I write four 9-bit words to TXFIFO and start the burst with writing to XCH. This sends the first 9-bit burst and negates the Chip Select back to inactive. After Writing to XCH three more times, all data is sent, but the Chip Select signal negates between all bursts.

This (Figure 10-8) is what I expect, with 9-bit words:

correct.png

But this (Figure 10-9) is what I get, regardless of the position of SS_CTL bits

incorrect.png

In Linux this seems to work. However, I haven't checked, is the Chip Select implemented by SW or by HW.

I have been testing the functionality with a sligthly modified version of the example ecspi code in the board support package. (FreeRTOS_BSP_1.0.0_iMX7D)

ECSPI_SetSSMultipleBurst(BOARD_ECSPI3_BASEADDR, ecspiSelectChannel0, false);

ecspi_init_t ecspiInitConfig = {

    .clockRate = get_ecspi_clock_freq(BOARD_ECSPI3_BASEADDR),

    .baudRate = 500000,

    .mode = ecspiMasterMode,

    .burstLength = 8, // 9 -1

    .channelSelect = ecspiSelectChannel0,

    .clockPhase = ecspiClockPhaseSecondEdge,

    .clockPolarity = ecspiClockPolarityActiveLow,

    .ecspiAutoStart = false

};

ECSPI_XFER_Config(&ecspiInitConfig);

...

bool ECSPI_XFER_TransmitBurst(int command)

{

    uint8_t bytes;

    uint32_t data;

    ECSPI_SetBurstLength(ECSPI3, 8); // 9 bits - 1

   

    /* Fill the TXFIFO */

    while((ecspiState.txSize > 0) && (ECSPI_GetStatusFlag(ECSPI3, ecspiFlagTxfifoFull) == 0))

    {

        bytes = 1;            

        if(!(ecspiState.txBuffPtr))

        {

            data = 0xFFFFFFFF;

        }

        else

        {

            data = 0;

            data = *(ecspiState.txBuffPtr)++;

            if (command)

            {

                command = 0;

            }

            else

            {

                data |= 1 << 8;

            }

        }

              

        ECSPI_SendData(ECSPI3, data);

       

        ecspiState.txSize -= bytes;

        if(ecspiState.rxBuffPtr)

        {

            ecspiState.rxSize += bytes;

        }

    }

    /* start transmission */

    ECSPI_StartBurst(ECSPI3); // Transfer the first word

    while(ECSPI_GetTxfifoCounter(ECSPI3) > 0)

    {

        // Transfer the rest of the words

        while(ECSPI_GetStatusFlag(ECSPI3, ecspiFlagTxfifoTc) == 0);

        ECSPI_StartBurst(ECSPI3);

    }

    return true;

}

Questions:

- Is there something wrong with my configuration, or is the HW working incorrectly? Of course the SW developers tend to blame HW rather than own code.

- Should Writing to XCH transfer all words that are in TXFIFO or just the first one, like in my case?

Labels (2)
Tags (4)
0 Kudos
16 Replies

1,755 Views
einarikoivu
Contributor I

I got my workaround working. I extended the burst length to contain the total number of bits in the data (multiple of 9 in my case) and implemented a lot of bitwise operations to get all 9-bit words one after another.

But this question is still unanswered: How can I get chip select behavior like in figure 10-8 with BURST_LENGTH=8?

0 Kudos

1,755 Views
Yuri
NXP Employee
NXP Employee

Hello,

  As has been mentioned, the figure is not fully accurate regarding the BURST LENGTH.

Regards,

Yuri.

0 Kudos

1,755 Views
danhagler
Contributor I

The Reference Manual is not fully accurate regarding the BURST LENGTH.

Yuri or any other NXP representative,

I have run into this same issue on the iMX6soloX. The above quoted response does not answer the following relevant questions:

  • What exactly is not accurate in the Reference Manual?
    • Please be very clear and concise as to what is incorrect.
    • Please be very clear and concise as to what it should say instead that is correct.
  • Does the processor do single SPI bursts with multiple BURST LENGTH words, as documented, or doesn't it?
    • Please give a clear and definitive answer of either "yes, it does" or "no, it does not".

Saying the Manual is not fully accurate, leaves open the following possibilities:

  • The processor does do single SPI bursts with multiple BURST LENGTH words, but the Reference Manual does not explain how to achieve this.
  • The processor does not do single SPI bursts with multiple BURST LENGTH words, and so, the Reference Manual is completely incorrect.

So please clarify. If the processor does not do single SPI bursts with multiple BURST LENGTH words, please refer me to the official NXP errata that documents this fact.

If the processor does do single SPI bursts with multiple BURST LENGTH words, please refer me to anything official that accurately describes how to achieve this.

0 Kudos

1,755 Views
Yuri
NXP Employee
NXP Employee

Hello

  The eCSPI supports single SPI bursts with multiple BURST LENGTH words, assuming that

in the case, when BURST LENGTH is greater than 32, full 32-bit word(s) from FIFO will be sent,

except the recent one.

Have a great day,
Yuri

--------

0 Kudos

1,755 Views
danhagler
Contributor I

Thanks for the response Yuri,

I have had success sending BURST LENGTH of 1 bit to 4096 bits, by filling full 32-bit word(s), with the final 32 bit word only containing BURST LENGTH MOD 32 relevant bits. However, when I try to send multiple BURST LENGTH words that are < 32 bits each, I have not been able to get that to work with SS_CTL set to 0.

When I set SS_CTL to 1, the BURST LENGTH < 32 bit words I load into the TX FIFO are sent, with the SS pin going inactive between each BURST LENGTH word as expected with SS_CTL == 1. However, when I set SS_CTL to 0 and fill the TX FIFO with BURST LENGTH < 32 words, it sends just one burst of BURST LENGTH and nothing else happens. The TX FIFO still contains additional BURST LENGTH < 32 words, but nothing more is transmitted.

In all cases, I am setting SMC to 0 and loading the TX FIFO and then setting XCH to 1.

Is there some other interrupt I need to enable and do something in the ISR to get the remaining words of BURST LENGTH < 32 to be sent out?

0 Kudos

1,755 Views
Yuri
NXP Employee
NXP Employee

 

Hello,

 

  Do You mean that BURST LENGTH MOD 32 bits (remaining bits in recent / first FIFO word) are not sent, for SS_CTL = 0. Say, BURST LENGTH corresponds 35 bits (BURST LENGTH = 34) and only 32 bits are really sent ; remaining 3 bits are not sent ?

 

Regards,

Yuri.

0 Kudos

1,755 Views
danhagler
Contributor I

I mean that I set BURST LENGTH to something < 31 (bits < 32), say BURST LENGTH = 8 (9 bits), and load multiple 32 bit values into the TX FIFO, say 3 wrties to the TXDATA register of 0x00000101, 0x000001F2, 0x000001E3, then set XCH to 1. With SS_CTL = 0, only the first 9 bit word, 0x101, is transmitted.

For SS_CTL = 1, all 3 words of 9 bits are sent. With SS_CTL = 1, chip select active during each 9 bit word transmission and inactive between each 9 bit word, as expected.

BURST LENGTH = 8

SS_CTL = 1

TEEN = 1

TE interrupt - write 0x00000101 to TXDATA, write 0x000001F2 to TXDATA, write 0x000001E3 to TXDATA

CS active, 9 bits 0x101, CS inactive, CS active, 9 bits 0x1F2, CS inactive, CS active, 9 bits 0x1E3, CS inactive.

TE interrupt - signal complete semaphore

Success!

For SS_CTL = 0, only 1 word of 9 bits are sent, chip select is held active indefinitely and the TX FIFO has 2 words waiting to be sent, but they are not sent. I expected all 3 words of 9 bits to be sent, as happens when SS_CTL = 1. The only difference of behavior I expected is that chip select would remaining active across the transmission of all 5 words of 9 bits.

BURST LENGTH = 8

SS_CTL = 0

TEEN = 1

TE interrupt - write 0x00000101 to TXDATA, write 0x000001F2 to TXDATA, write 0x000001E3 to TXDATA

CS active, 9 bits 0x101, nothing else happens on the SPI bus

No TE interrupt occurs, since there are 2 words in the FIFO waiting to be sent

Timeout waiting for complete semaphore.

FAILURE!

0 Kudos

1,755 Views
Yuri
NXP Employee
NXP Employee

Hello,

   You may get operations as shown on the Figure 10-8 (SPI Burst While SS_CTL[3:0] is Clear)

of the RM (Rev. 0.1, 08/2016), but please take into account, that the description under the figure

is not fully correct. "The maximum length of a single SPI burst is defined in the BURST LENGTH

field of the ECSPI_CONREG control register".  Really the maximum length of the single SPI burst

is defined by FIFO. When FIFO is overflowed the SS is negated.    

Regards,

Yuri.

0 Kudos

1,755 Views
einarikoivu
Contributor I

I appreciate your answers, Yuri.

If your answer is correct, I don't get, what's the point of SS_CTL. The reference manual states the following:

"When the SPI SS Wave Form Select (SS_CTL[3:0]) is set, the current operation is multiple bursts transfer. When the SPI SS Wave Form Select (SS_CTL[3:0]) bit is cleared, the current operation is single burst transfer. A SPI burst can contains multiple words as defined in the BURST LENGTH field of the ECSPI_CONREG register."

and further:

"In Figure 10-8, two 8-bit bursts in the TXFIFO have been combined and transmitted in one SPI burst. The maximum length of a single SPI burst is defined in the BURST LENGTH field of the ECSPI_CONREG control register. (Figure 10-8 corresponds to a BURST LENGTH of 8.) This provides a way for transferring a longer SPI burst by writing data into TXFIFO while the ECSPI is transmitting."

and even further, SS_CTL is described as following in ECSPIx_CONFIGREG field descriptions:

SPI SS Wave Form Select. In master mode, this field controls the output wave form of the Chip Select (SS) signal when the SMC (Start Mode Control) bit is cleared. The SS_CTL are ignored if the SMC bit is set.

Thus: it should be possible to write nine-bit words to TXFIFO and let HW take care of the rest so that result is one single burst with SS not negating in between. Currently SS_CTL has no effect on the SPI behavior in master mode.

So, I think I need the function of SS_CTL explained a bit more. I still believe that the HW should work as described in the reference manual, or this should be fixed in errata. The reference manual is not just "not fully accurate", but the whole paragraph is totally incorrect, if the behavior is as you mentioned.

0 Kudos

1,758 Views
Yuri
NXP Employee
NXP Employee

Hello,

  According to SS_CTL bit field description, when SS_CTL= 0 : in master mode - only one SPI burst

will be transmitted (without CS negation), assuming transfer total number of bits / words, configured

via  BURST_LENGTH.


Have a great day,
Yuri

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 Kudos

1,758 Views
einarikoivu
Contributor I

Hi,

Thanks a lot for your response. That answered to the second part of my question. Having SS_CTL= 0 should transfer only one burst, not all the words that are in TXFIFO.

But, there's yet the first part - the more important part unanswered: how do I get signal that is illustrated in figure 10-8? I have set SS_CTL= 0, BURST_LENGTH = 8 and SMC=0. Still I get Chip Select signal behave like in figure 10-9. It negates between all bursts.

0 Kudos

1,755 Views
Yuri
NXP Employee
NXP Employee

Hello,

  To transfer N 9-bit words it is needed to set BURST_LENGTH, assuming that burst is N * 9 bit,

and pack the data to the FIFO with 32-bit port. 

Regards,

Yuri.

0 Kudos

1,755 Views
einarikoivu
Contributor I

I don't think that the buffer conversion should be necessary according to the documentation. i.MX7 reference manual states: "Figure 10-8 corresponds to a BURST LENGTH of 8". Thus; it should be possible to stack 9-bit words to TXFIFO and let the processor to handle the rest. Conversing long 8-bit data buffers to 9-bit format with command bits in front is quite a CPU intensive task.

0 Kudos

1,755 Views
Yuri
NXP Employee
NXP Employee

Perhaps it would be easier to use a GPIO as Slave Select signal.

Regards,

Yuri.

0 Kudos

1,755 Views
einarikoivu
Contributor I

Of course the easiest way would be to just let HW take care of it, like described in the reference manual.

I already tried the GPIO way, but I can't get timings right. setting GPIO up and down is extremely slow. Latency was more than 1ms, if I remember correctly. I'm not sure why it took so long to switch the pin up and down.

Now I'm on my way to implement the workaround to put the nine-bit words one after another to uint8_t buffer. That's far from optimal solution. I wish someone from Freescale/NXP could comment on this.

0 Kudos

1,755 Views
Yuri
NXP Employee
NXP Employee

Hello,

  The Reference Manual is not fully accurate regarding the BURST LENGTH.

Regards,

Yuri.

0 Kudos