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?
Thanks for the info!
Doug
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
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
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
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