KL17 SPI always reads 0xff, scope shows valid MISO waveform.

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

KL17 SPI always reads 0xff, scope shows valid MISO waveform.

2,266 Views
dougbaker
Contributor III

I have a FRDM-KL-27Z eval board where we changed the CPU to a KL17.  We hooked up an ST h3lis331dl accelerometer that has a SPI interface and wired it to the KL27 board.   On the KL27 board, we have the SPI from the ST h3lis331dl hooked up as follows.

 

PTD0 is the chip select.    PTD0-1 On J1 connector

PTD1 is the SPI0 clock      PTD1-3 On J1 connector

PTD2 is the SPI0 MOSI     PTD2-5 On J1 connector

PTD3 is the SPI0 MISO     PTD3-7 On J1 connector

 

I am using KDS 3.2.0 as a dev environment am I am starting from an example SPI_polling_transfer.

 

On the ST h3lis331dl, there is a register I can read called the WHO_AM_I that will reply a fixed reply of 0x32.  Based on some sample code and the documentation for the Kinetis, I can confirm that the SPI is working properly by looking at the waveforms on a scope.  The scope shows is the following:

 

1 The chip select asserted

2 The SPI clock starts and the MOSI has the correct waveform for the address for the WHO_AM_I register.   This is an 8 bit burst on the bus.

3 there is a slight pause in the SPI clock

4 The SPI clock starts again and the correct reply is seen on the MISO pin.  The scope shows that MISO had the data 0x32.

5 The chip select is de asserted

6 the problem I have is when I get the data from the SPI, I do not get the data value I expect.  I expect to see the value 0x32 but I see 0xff. 

 

My Pin mux is:

    CLOCK_EnableClock(kCLOCK_PortD);

    //PORT_SetPinMux(PORTD, 0U, kPORT_MuxAlt2);   // SPI chip select   //automatic CS

    PORT_SetPinMux(PORTD, 1U, kPORT_MuxAlt2); // SPI0-SCK  PTD1

    PORT_SetPinMux(PORTD, 2U, kPORT_MuxAlt2); // SPI0-MOSI PTD2

    PORT_SetPinMux(PORTD, 3U, kPORT_MuxAlt2); // SPI0-MISO PTD3

 

 

My SPI config is:         

   SPI_MasterGetDefaultConfig(&masterConfig);

   sourceClock = CLOCK_GetFreq(EXAMPLE_SPI_MASTER_SOURCE_CLOCK);

   SPI_MasterInit(SPI_0_MASTER, &masterConfig, sourceClock);

 

 

My code to read the SPI is the following:      

 

#define BUFFER_SIZE 64U

uint8_t spi_data_IN[BUFFER_SIZE];  // <<< this is a global.

 

spi_transfer_t xfer = {0};

 

 

<SNIP>

           

 memset(spi_data_IN, 0x55, sizeof(spi_data_IN));  // init the data to a known value

 

/* SPI master start transfer */

            xfer.txData = (uint8_t *) SPI_data.sendDataSPI;

            //xfer.rxData = (uint8_t *) &SPI_data.receivedDataSPI[0];

            xfer.rxData = spi_data_IN;

            xfer.dataSize = SPI_data.totalDataBytes;

            spi_accel_chipselect(TRUE); // select the device to read/write (chip select)

 

           reuturnValue = SPI_MasterTransferBlocking(SPI_MASTER, &xfer); // note the return value is OK

 

           spi_accel_chipselect(FALSE); // select the device to read/write (chip select)

       

      

          PRINTF("post read Data rx = %x %x %x  %x %x\r\n",

                                        spi_data_IN[0],

                                        spi_data_IN[1],

                                        spi_data_IN[2],

                                        spi_data_IN[3],

                                        spi_data_IN[4]);

 

  OUTPUT data from above print statement:  post read Data rx = ff ff 55  55 55

 

My question is why do I read in the buffer a value of 0xff and not 0x32 when the scope shows I should be reading 0x32? 

 

  • I can confirm that the MISO pin has a good connection between the PTD3-7 pin on the eval board and the physical pin 60 on the CPU.

 

 

  • If I use masterConfig.pinMode = kSPI_PinModeOutput;, the waveforms on the scope are still good but I read 0x8f. The 0x8f is what I write on the first byte.
Labels (1)
0 Kudos
5 Replies

1,571 Views
dougbaker
Contributor III

Thanks for the info!

Doug

0 Kudos

1,571 Views
randythomas
Contributor I

I've just experienced a similar problem with the KL27 & found the root cause.  The BootLoader leaves PortC (pins 4,5,6 & 7) assigned for SPI0 use.  Configuring SPI0 for the PortD pins results in a conflict which, in particular, prevents MISO data from being latched into the SPI0 data register from the PortD pin.  The solution is to re-assign the PortC pins to GPIO (or anything other than SPI0 duty!) during the init phase of your code, allowing the PortD SPI0 definitions to actually work!

(Beware -- the Boot also leaves pins defined for LPUART0 & I2C0 use upon exit.....  Refer to the Kinetis Bootloader Peripheral Pinmux table in the manual.)

Hope this helps.

Randy

0 Kudos

1,571 Views
xiangjun_rong
NXP TechSupport
NXP TechSupport

Hi, Doug,

I have checked the required spi timing of the slave spi STM product, you have to set both the CPHA bit and CPOL bit in masterConfig so that the spi timing are matched. I copy the spi timing of both slave and master devices.

Pls check the two bits.

Hope it can help you

BR

Xiangjun Rong

pastedImage_1.png

0 Kudos

1,571 Views
dougbaker
Contributor III

As far as the SPI not working following a reset from boot, there is no change by changing the clock phase and polarity.  To restate the problem, if I jump to boot, then  I do a reset in boot to get the CPU to begin executing the application code, the SPI does not work properly.  If I hit the reset button on the board or just power up the board and run, the SPI will work properly.

Doug

0 Kudos

1,571 Views
dougbaker
Contributor III

I recently learned some more about this problem.  When I update the code, I am using blhost.exe to do the update from the PC over RS232.  After the firmware update, I use the reset command in blhost to get the CPU to jump back to the application and begin executing the new code.  What I discovered is when the CPU begins executing code from blhost, it does not read the SPI properly.  If I then reset the CPU by using the reset button on the eval board, the SPI reads properly.  If I do a cold boot by applying power to the board, the same code will boot up and work properly.  One other test I did was put the CPU in the boot code but instead of doing a firmware update, I only commanded the CPU to reset and when the code came out of reset, the SPI did not work properly.

 

If I apply power and the board boots up and runs properly, I assume that everything that needs to be configured on the CPU that needs to be is configured properly by the application.  When the CPU goes  from boot to application, it appears that the boot is leaving something in a bad state.

 

FYI, use the following to put the CPU into the bootloader:

 

void jumToBootloader(void)

{

       uint32_t runBootloaderAddress;

 

       runBootloaderAddress = **(uint32_t **) (0x1c00001c);

       runBootloader = (void (*) (void * arg)) runBootloaderAddress;

 

       runBootloader(NULL);

 

}

 

Any ideas?

Thanks,

Doug

0 Kudos