SPI shift register value on Kinetis

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

SPI shift register value on Kinetis

Jump to solution
1,813 Views
stoneface
Contributor II

Hi all,

I have a problem with the Kinetis SPI module

MCU: K10DX32

software: CodeWarrior Development Studio 10.6

programmer: PE micro multilink universal

The SPI module is configurated as slave. When data is coming in at SIN an interrupt is generated where the data are saved in a buffer. This is working.

From other MCUs and applications I'm used that the incoming data are automatically shifted out to SOUT when the next data is coming. But here the value at SOUT is always zero.

Then I tried to set the value of the shift register manually by writing the desired value into SPI0_PUSHR_SLAVE. This results in the following behaviour:

- data received, SPI0_PUSHR_SLAVE set with value1,        0 is shifted out  => ok

- data received, SPI0_PUSHR_SLAVE set with value2, value1 is shifted out  => ok

- data received, SPI0_PUSHR_SLAVE set with value3, value1 is shifted out  => not ok

- now always value1 is shiftet out

It seems that writing to SPI0_PUSHR_SLAVE works exactly one time. Enabling or disabling the FIFO shows the same behaviour.

I analysed a lot of flags and registers to understand what happens, but without success.

my configuration:

pastedImage_1.png

interrupt code:

/*

** ===================================================================

**     Interrupt handler : SPI

**

**     Description :

**         User interrupt service routine.

**     Parameters  : None

**     Returns     : Nothing

** ===================================================================

*/

PE_ISR(SPI)

{

  /* Write your interrupt code here ... */

   

    // save the input data

    spidata = SPI0_POPR;

    // set the FIFO register with some value that should appear at the output next time

    SPI0_PUSHR_SLAVE = value;

    // clear the Receive FIFO Drain Flag

    SPI0_SR |= SPI_SR_RFDF_MASK;

}

regards,

Jörg

Labels (1)
0 Kudos
1 Solution
1,041 Views
stoneface
Contributor II

Hi,

finally I found the reason for my problem.

I have a constellation with exactly one master and exactly one slave, so the SS line can be kept low all the time (tied to ground). So I thought, because it's working with other MCUs that I programmed.

But the Kinetis seems to dislike when the SS line is already low during initialization. Interestingly the Rx is working as normal, only the Tx part is annoying.

The solution is to use the regular SS connection from the master or as a workaround to connect SS of the slave to a GPIO that is high on reset or power up and goes low after initialization.

regards,

Jörg

View solution in original post

0 Kudos
5 Replies
1,042 Views
stoneface
Contributor II

Hi,

finally I found the reason for my problem.

I have a constellation with exactly one master and exactly one slave, so the SS line can be kept low all the time (tied to ground). So I thought, because it's working with other MCUs that I programmed.

But the Kinetis seems to dislike when the SS line is already low during initialization. Interestingly the Rx is working as normal, only the Tx part is annoying.

The solution is to use the regular SS connection from the master or as a workaround to connect SS of the slave to a GPIO that is high on reset or power up and goes low after initialization.

regards,

Jörg

0 Kudos
1,041 Views
adriancano
NXP Employee
NXP Employee

Hi,

Where you are updating the value of the variable "value"?

Regards,

Adrian

0 Kudos
1,041 Views
stoneface
Contributor II

Hi Adrian,

sorry for my late reply. I was busy with some urgent stuff.

"value" is set in the interrupt routine.

It can be a constant like in the following example:

PE_ISR(SPI)

{

     /* Write your interrupt code here ... */

     // save the input data

     spidata = SPI0_POPR;

     // set the FIFO register with some value that should appear at the output next time

     if (cnt==0) {

          SPI0_PUSHR_SLAVE = 0xAA;

          cnt++;

     } else {

          SPI0_PUSHR_SLAVE = 0xBB;

          cnt = 0;

     }

     // clear the Receive FIFO Drain Flag

     SPI0_SR |= SPI_SR_RFDF_MASK;

}

The output should toggle between AA and BB, but it's always AA.

It can be set by a variable (global or not) like in the following example:

PE_ISR(SPI)

{

     /* Write your interrupt code here ... */

     // save the input data

     spidata = SPI0_POPR;

     // set the FIFO register with some value that should appear at the output next time

     if (cnt==0) {

          SPI0_PUSHR_SLAVE = cnt ;

          cnt++;

     } else {

          SPI0_PUSHR_SLAVE = cnt ;

          cnt = 0;

     }

     // clear the Receive FIFO Drain Flag

     SPI0_SR |= SPI_SR_RFDF_MASK;

}

The output should toggle between 0 and 1, but it's always 0.

It seems that the output is always the value that was used when setting SPI0_PUSHR_SLAVE the first time.

regards

Jörg

0 Kudos
1,041 Views
adriancano
NXP Employee
NXP Employee

Hi,

I apologize for the late response. I have some suggestions to do in order to test the behavior of the SPI module.

Debug the code an set a breakpoint inside the else statement to ensure that the instruction is being executed an check the values written to the SPI0_PUSHR_SLAVE register when the instruction is executed, if you are not using FIFO then you have a one entry FIFO, please check the value stored there to see if the value is being stored or not.

Also it is possible that the FIFO is ignoring the writes to it because is full, you can check the TFFF flag just before trying to write to the PUSH register to ensure a empty FIFO (a full FIFO ignores any attempt to write to it).

Hope this information can help you.

Best Regards,
Adrian Sanchez Cano
Technical Support Engineer
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 Kudos
1,041 Views
stoneface
Contributor II

Hi Adrian,

I debugged the code as you proposed.

The interrupt routine is as follows:

PE_ISR(SPI)

{

     /* Write your interrupt code here ... */

     // save the input data

     spidata = SPI0_POPR;

     // set the FIFO register with some value that should appear at the output next time

     if (cnt==0) {

          SPI0_PUSHR_SLAVE = 0xAA;

          cnt = 1;

     } else {

          SPI0_PUSHR_SLAVE = 0xBB;

          cnt = 0;

     }

     // clear the Receive FIFO Drain Flag

     SPI0_SR |= SPI_SR_RFDF_MASK;

}

FIFO is disabled.

The master sends four bytes, so the interrupt is triggered four times.

spi.jpg

The receiving of the incoming data works fine, but the flags and registers for the transmitter functions are not as expected.

I also experimented with setting/resetting of several flags at several points, all without any influence on the behaviour.

Maybe the initialisation is wrong? This is done with the Processor Expert.

best regards

Jörg

0 Kudos