I'm trying to execute and interrupt based I2C and SPI transfer on a kl27z MCU on a FRDM-KL27Z board. Examples from the SDK points to the use of SPI/I2C_MasterTransferNonBlocking with a callback function to indicate transfer is finished. However I couldn't quite understand how TransferNonBlockin works and when the interrupt is triggered. Can anyone enlighten me? Also, I would like to know the correct way of setting up FIFO in SPI1 as it is not stated anywhere in the examples.
I've posted the question on the Kinetis SDK section but has yet to receive a response.
Any help is appreciated.
Hi Bob and Gabriel,
You guys seem to have quite a bit of experience with SPI on the KL27Z parts.
I have a problem at the moment where my program sometimes gets stuck on
while ((base->S & SPI_S_SPRF_MASK) == 0U)
between SPI_WriteNonBlocking() and SPI_ReadNonBlocking() in SPI_MasterTransferBlocking().
It seems to be a throughput related issue. I have a 1ms event reading the SPI device and then transferring data via a USB report.
If I run at 2ms it works fine. I'm thinking my next step is to add a timeout counter to the while loop, but would be keen to understand why this might be happening in the first place.
I haven't found any errata or other comments that describe this issue.
Blocking only holds things up for ~30us.
I've tried using non blocking but this doesn't seem to work when switching between 8bit and 16bit transfer mode.
It turns out I was missing the pullup resistors on the I2C. However, I'm still having problems with the I2C. If the master is not connected to anything, the clock behaves as expected, but when it is connected to a slave (in this case I2C1 on the KL27) it still shows a triagular wave, despite the data being sent succesfully.
Also I'm having trouble reading data from the I2C slave but this might just be the re-start problem that Bob stated earlier.
Furthermore, after digging around the SPI driver a bit, I've seen that in the SPIMasterTransferNonBlocking there is no line of code, as far as I'm aware of, that tells the spi to read. This function only calls SPI_SendTransfer which in turn call SPI_WriteNonBlocking, where in my understanding it just loads up the SPI transmit buffer. However, in the example, this function manages to read data. Can anyone explain how this works? Maybe I'm missing some details.
Furthermore, how large is the SPI buffer? I can't seem to find any documented buffer size in the datasheet nor the user manual. Only the 64-bit fifo is listed.
Thanks again, sorry for the ever expanding questions.
In SPI Transmit and Receive is symmetrical. As the Tx bits are shifted out, the Rx bits are shifted in.
So there is no such thing as a SPI Read Command equivalent as found in a UART.
A Read will require a SPI Tx Write of any arbitrary data just to generate the clock pulses to get the Rx data shifted in, if nothing meaningful actually needs to be transmitted.
I'm not familiar with the code you are looking at to comment further.
If the clock signal is triangular waveform, as Bob said, pls connect 4.7K ohm pull-up resistor for SCL/SDA pins. Secondly, pls decrease the IIC baudrate.
Pls have a try.
Hi, Thanks for the help, I've managed to get the SPI working.
However, not so with the I2C. I've been trying to test it on an oscilloscope and I'm seeing nothing but both SCL and SDA line constantly high.
Could this issue be related to what Mr Paddock noted in an earlier comment?
If SDA/SCL are stuck high it is a different problem than this issue with broken Repeated Start in the KL27 family.
Check the port configurations and clocks.
You should see at least eight transitions of SCL on a master write even if no slave is connected.
If that is not being seen the line is being held high by something (3p3 Ohm resistor put in place of 3k3 pull up? Strange things do happen.) or the port is not configured correctly.
I have done further testing with the scope with both the slave connected and disconnected to confirm my earlier observations. I have seen now that both lines remain low when disconnected at all time. Even when I2C_MasterTransferNonBlocking is called, I could not see any transitions on both lines after trying to set an edge trigger for both of them. When connected, however, I can now see the start condition and some sort of clocking. But the clock is kinda weird. It's more like a triangular wave that a normal square wave of a clock signal. Any thoughts?
What pull up resistors do you have on the lines and to what voltage are they connected?
Triangle indicates to much capacitance for the resistor value.
Linear Tech. makes an active pull-up for I2C for the cases where high speed and high capacitance is required.
Also it is ambiguous as to which parts have true Open Drain outputs as is expected by the I2C Standard, as far as to if they are five volt tolerant (yet more bad documentation).
It is always the Master that generates the clock at the start of the transmission.
If things are configured correctly it will not mater if the Slave is connected for the first eight clock pulses, that is until the Slave is expected to put the Ack on the SDA line. What happens next Ack/NAck really depends on how the code is setup.
If the SPI is set up in master mode, it do not need slave spi handshaking signal, so you can see the SPI timing even if you do not connect any slave spi device.
But Even if you set up the IIC module in master mode, the master IIC module needs ACK handshaking signal from slave IIC device, if you want to observe IIC timing signal(SDA/SCL), you have to connect slave IIC module. When the IIC module do not receive ACK signal from slave IIC device, the master IIC module will fail, so there is not IIC timing.
In conclusion, pls connect IIC slave device when you run code.
Hope it can help you.
I used the second I2C module in the KL27 as the slave in the test and I still see nothing. Furthermore, the slave callback did execute while the master's callback never executes.
Regarding your question, pls refer to the example in SDK2.0.
Regarding the driver of SDK, I think this is the software architecture. The SPI uses interrupt mechanism to transfer data, user calls the high level api function to transfer data via the large buffer instead of the direct module register, the SPI interrupt service routine writes the data from the buffer to SPI transmitter register, or read the SPI receiver register to buffer. user is required to call high level api function to write data to the buffer or read data from the buffer.
If you use RTOS, a semaphore is established, in the ISR, sem_post() is called. In the transfer function, sem_wait() is called, at the same time, the chip is blocked at the sem_wait() function.
If you do not use RTOS, you call the SPI_MasterTransferNonBlocking(), "NonBlocking" means that the api function returns immediately after writing the transmitted data to the buffer. If you can call the SPI_MasterTransferBlocking(), "Blocking" means that the function has a while() loop, which polls if the predefined number of data has been been transferred, after all data have been transferred, the api function can return. In both SPI_MasterTransferNonBlocking() and SPI_MasterTransferBlocking(), callback function is supported, after the number of data has been transferred, the callbacl function is called automatically.
You can set the FIFOMODE bit in SPIx_C3 to enable FIFO, if you use FIFO mode, the KL27 can increase it's efficiency, for example, you can write 8 byte in ISR instead of one as usual.
Hope it can help you
I know this is not the response you are hoping for whoever it might save you from wasting a lot of time.
The I2C hardware on the KL43/KL27 family is broken as explained here:
Double Buffered I2C Difficulties (eg. KL27)
NXP seems to have no interest in issuing a proper errata or fixing the parts :-(