
- 新着としてマーク
- ブックマーク
- 購読
- ミュート
- RSS フィードを購読する
- ハイライト
- 印刷
- 不適切なコンテンツを報告
Hello,
I am implementing SPI communication between the S32K144 MCU and MAC-PHY (LAN8650).
For Control Transaction Write/Read (where the master writes/reads a register value to/from the slave), the process follows the TC6 SPI protocol as shown in the image below:
Before stepping forward to actual register read/write to MAC-PHY, I thought of testing it with some dummy data and verify it by probing in at MOSI of S32K144 and SDI of MAC-PHY(LAN8650) chip. With that I could successfully send 16 bit and 32 bit data, but whereas no data transactions happening for 64 bit transfer.
As per above picture inorder to read/ write the slave register it should be 64 bits(Control header + Data) or higher.
The working code 32 bits dummy data transfer is as follows :
#include "S32K144.h" /* include peripheral declarations S32K144 */
uint32_t tx_32bits = 0xFD00FD00;
//uint32_t tx_32bits_array[2] = {0xFD00, 0X1010};
uint32_t LPSPI0_32bits_read; /* Returned data in to SPI */
void LPSPI0_init_master(void) {
PCC->PCCn[PCC_LPSPI0_INDEX] = 0; /* Disable clocks to modify PCS ( default) */
PCC->PCCn[PCC_LPSPI0_INDEX] = 0xC6000000; /* Enable PCS=SPLL_DIV2 (40 MHz func'l clock) */
LPSPI0->CR = 0x00000000; /* Disable module for configuration */
LPSPI0->IER = 0x00000000; /* Interrupts not used */
LPSPI0->DER = 0x00000000; /* DMA not used */
LPSPI0->CFGR0 = 0x00000000; /* Defaults: */
/* RDM0=0: rec'd data to FIFO as normal */
/* CIRFIFO=0; Circular FIFO is disabled */
/* HRSEL, HRPOL, HREN=0: Host request disabled */
LPSPI0->CFGR1 = 0x00000001; /* Configurations: master mode*/
/* PCSCFG=0: PCS[3:2] are enabled */
/* OUTCFG=0: Output data retains last value when CS negated */
/* PINCFG=0: SIN is input, SOUT is output */
/* MATCFG=0: Match disabled */
/* PCSPOL=0: PCS is active low */
/* NOSTALL=0: Stall if Tx FIFO empty or Rx FIFO full */
/* AUTOPCS=0: does not apply for master mode */
/* SAMPLE=0: input data sampled on SCK edge */
/* MASTER=1: Master mode */
LPSPI0->TCR = 0x1100001F; /* Transmit cmd: PCS1, 32 bits, prescale func'l clk by 4, etc*/
/* CPOL=0: SCK inactive state is low */
/* CPHA=0: On the rising edge of SCLK the data is captured, while on the falling edge of SCLK the data will change
/* PRESCALE=2: Functional clock divided by 2**2 = 4 */
/* PCS=1: Transfer using PCS1 */
/* LSBF=0: Data is transfered MSB first */
/* BYSW=0: Byte swap disabled */
/* CONT, CONTC=0: Continuous transfer disabled */
/* RXMSK=0: Normal transfer: rx data stored in rx FIFO */
/* TXMSK=0: Normal transfer: data loaded from tx FIFO */
/* WIDTH=0: Single bit transfer */
/* FRAMESZ=31: # bits in frame = 31+1=32 */
LPSPI0->CCR = 0x04090808; /* Clock dividers based on prescaled func'l clk of 100 nsec */
/* SCKPCS=4: SCK to PCS delay = 4+1 = 5 (500 nsec) */
/* PCSSCK=4: PCS to SCK delay = 9+1 = 10 (1 usec) */
/* DBT=8: Delay between Transfers = 8+2 = 10 (1 usec) */
/* SCKDIV=8: SCK divider =8+2 = 10 (1 usec: 1 MHz baud rate) */
LPSPI0->FCR = 0x00000003; /* RXWATER=0: Rx flags set when Rx FIFO >0 */
/* TXWATER=3: Tx flags set when Tx FIFO <= 3 */
LPSPI0->CR = 0x00000009; /* Enable module for operation */
/* DBGEN=1: module enabled in debug mode */
/* DOZEN=0: module enabled in Doze mode */
/* RST=0: Master logic not reset */
/* MEN=1: Module is enabled */
}
void LPSPI0_tx_32bits (uint32_t send) {
while((LPSPI0->SR & LPSPI_SR_TDF_MASK)>>LPSPI_SR_TDF_SHIFT==0);
/* Wait for Tx FIFO available */
LPSPI0->TDR = send; /* Transmit data */
LPSPI0->SR |= LPSPI_SR_TDF_MASK; /* Clear TDF flag */
}
uint32_t LPSPI0_rx_32bits (void) {
uint32_t recieve = 0;
while((LPSPI0->SR & LPSPI_SR_RDF_MASK)>>LPSPI_SR_RDF_SHIFT==0);
/* Wait at least one RxFIFO entry */
recieve= LPSPI0->RDR; /* Read received data */
LPSPI0->SR |= LPSPI_SR_RDF_MASK; /* Clear RDF flag */
return recieve; /* Return received data */
}
void PORT_init (void) {
//Master:
PCC->PCCn[PCC_PORTB_INDEX] |= PCC_PCCn_CGC_MASK;
PORTB->PCR[2] |= PORT_PCR_MUX(3); /*Port B2: MUX = ALT3, SCK*/
PORTB->PCR[3] |= PORT_PCR_MUX(3); /*Port B3: MUX = ALT3, SIN*/
PORTB->PCR[4] |= PORT_PCR_MUX(3); /*Port B4: MUX = ALT3, SOUT*/
PORTB->PCR[5] |= PORT_PCR_MUX(3);
}
int main(void) {
uint32_t counter = 0;
volatile int i;
WDOG_disable();
SOSC_init_8MHz(); /* Initialize system oscillator for 8 MHz xtal */
SPLL_init_160MHz(); /* Initialize SPLL to 160 MHz with 8 MHz SOSC */
NormalRUNmode_80MHz(); /* Init clocks: 80 MHz sysclk & core, 40 MHz bus, 20 MHz flash */
LPSPI0_init_master();
PORT_init();
for (;;) {
LPSPI0_tx_32bits(tx_32bits);
LPSPI0_32bits_read = LPSPI0_rx_32bits();
}
return 0;
}
Note : For 64 bit data transfer, I changed TCR[FRAMESZ]=3F and changed respective data types and values.
My questions are:
1. Is S32K144 doesnt support whole 64 bit transfer in one go? [In S32K1xx Series Reference Manual, Rev. 14 at start of page 1623 it means as the maximum frame size is 32 bits?]
2. If it supports only 32 bits, then kindly help me the way that on how to transfer >=64 bits of data.
3. Else if it supports 64 bits, then kindly point me out the changes i have to perform in the above code.
Thanks in advance!
解決済! 解決策の投稿を見る。


- 新着としてマーク
- ブックマーク
- 購読
- ミュート
- RSS フィードを購読する
- ハイライト
- 印刷
- 不適切なコンテンツを報告
Hi,
code looks normal, but I think a protocol looks little bit different. There should be 3 words transferred for single register writing/reading
For both read and write, the Control Header sent to the LAN8650/1 over SDI is always echoed back to the SPI host over SDO. When performing control writes, the register data sent over SDI is also echoed back over SDO.
Thus for write you send header, data, dummy words, For read you send header, dummy, dummy words.
So try that, measure SPI lines with scope /analyzer to know real frames. Also check header is correct.
BR, Petr
- 新着としてマーク
- ブックマーク
- 購読
- ミュート
- RSS フィードを購読する
- ハイライト
- 印刷
- 不適切なコンテンツを報告
Hello,
I'm responding to your post as I have experience implementing the TC6 protocol using the LAN8651 MAC-PHY chip from Microchip on the S32K314 MCU.
In my case, I used RTD 4.0.0 with S32 Design Studio 3.5, and configured the LPSPI driver as follows.
Based on this LPSPI driver, you should be able to configure a uint8_t tx and rx buffer with 12 elements and perform SPI communication accordingly.
ex) uint8_t spiRxBuffer[12], uint8_t spiTxBuffer[12]

- 新着としてマーク
- ブックマーク
- 購読
- ミュート
- RSS フィードを購読する
- ハイライト
- 印刷
- 不適切なコンテンツを報告
- 新着としてマーク
- ブックマーク
- 購読
- ミュート
- RSS フィードを購読する
- ハイライト
- 印刷
- 不適切なコンテンツを報告
Hello @Muthappan_Viswanthan
I'm really glad to hear that I was able to help for a change, since I'm usually the one receiving help.
If you have any further questions, feel free to leave a reply


- 新着としてマーク
- ブックマーク
- 購読
- ミュート
- RSS フィードを購読する
- ハイライト
- 印刷
- 不適切なコンテンツを報告
Hi,
yes, lpspi allows sending/receiving frame that has size larger that 32 bits. There could be several ways to do that.
1. set FRAMESZ to be multiple of 32, as per your need, how many words have to be transferred (up to 128)
2. set FRAMESZ to 31 for 32bit frame size and
a) control CS manually and fill data registers as per desired number of word transfer. You can refer to below code
https://community.nxp.com/t5/S32K/S32K146-LPSPI-with-ADXL314/m-p/1826209/highlight/true#M32845
b) use continuous selection, refer to https://community.nxp.com/t5/S32K/Continuous-Transfer-LPSPI-S32K14x/td-p/1830165
For sure above codes need to be modified for 32bit transfer.
Hope it helps.
BR, Petr

- 新着としてマーク
- ブックマーク
- 購読
- ミュート
- RSS フィードを購読する
- ハイライト
- 印刷
- 不適切なコンテンツを報告
Hello,
I used 2 a) [ set FRAMESZ to 31 for 32bit frame size and control CS manually and fill data registers as per desired number of word transfer.] with some dummy data and it worked. Now, when I tried with my actual task where I need to communicate with LAN8650 chip, I should write/read by sending control header first where the respective address should be present:
For this purpose I used the below code :
Here, I am trying to Write 0x00000000 to IMASK0 register address and trying to readback the same address in order to ensure the value has been written properly. But I got value has 0xC0000001 instead of 0xC0000000. (IMASK0 has 31 to 16 bits as reserved and Read-Only bits thus 0xC000 can be fixed even i try to write it as 0, thus we can neglect that) But the lower 16 bits are R/W and thus it should be 0.
For debugging purpose, in the above code I set breakpoint in the last while loop and it successfully hits (above picture) thus seems like write and read happening proper (not 100% sure, my assumption) but the value read is wrong.
I tried all possibilities and still couldn't find where it went wrong. Kindly guide me to solve this issue.
Thanks in advance.


- 新着としてマーク
- ブックマーク
- 購読
- ミュート
- RSS フィードを購読する
- ハイライト
- 印刷
- 不適切なコンテンツを報告
Hi,
code looks normal, but I think a protocol looks little bit different. There should be 3 words transferred for single register writing/reading
For both read and write, the Control Header sent to the LAN8650/1 over SDI is always echoed back to the SPI host over SDO. When performing control writes, the register data sent over SDI is also echoed back over SDO.
Thus for write you send header, data, dummy words, For read you send header, dummy, dummy words.
So try that, measure SPI lines with scope /analyzer to know real frames. Also check header is correct.
BR, Petr

- 新着としてマーク
- ブックマーク
- 購読
- ミュート
- RSS フィードを購読する
- ハイライト
- 印刷
- 不適切なコンテンツを報告
Thanks for your help so far.
I made the changes to transfer as 3x 32bit words for both read & write.
As per the statement from LAN8650 datasheet "When performing control writes, the register data sent over SDI is also echoed back over SDO", I am not getting echoed data as same as what I transmitted during write and read operations.
The modified code is as below:
void lan8650_write_imask0(uint32_t value) {
uint32_
t header = build_ctrl_header(1, 0x00, 0x000C, 0);
uint32_t read_tx_header2 = 0;
uint32_t read_tx_data2 = 0;
CS_LOW();
LPSPI0_tx_32bits(header); // Write header
(void)LPSPI0_rx_32bits(); //Read dummy bytes
LPSPI0_tx_32bits(value); // Write data
read_tx_header2 = LPSPI0_rx_32bits(); // Read Header Echo
LPSPI0_tx_32bits(0x00000000); // Write dummy data
read_tx_data2 = LPSPI0_rx_32bits(); // Read data Echo
CS_HIGH();
}
uint32_t lan8650_read_imask0(void) {
uint32_t header = build_ctrl_header(0, 0x00, 0x000C, 0);
uint32_t rx_header = 0;
uint32_t rx_data = 0;
CS_LOW();
LPSPI0_tx_32bits(header); // Send header
(void)LPSPI0_rx_32bits(); // Dummy data
LPSPI0_tx_32bits(0x00000000); // Dummy to clock header
rx_header = LPSPI0_rx_32bits(); // Read Header Echo
LPSPI0_tx_32bits(0x00000000); // Dummy to clock data
rx_data = LPSPI0_rx_32bits(); // Read data
CS_HIGH();
return rx_data;
}
And I measured the SPI lines of LAN8650 with scope and the observations are:
1. CS is LOW for the entire duration of 3x 32bits transfer.
2. SCK not seems to be continuous. After each 32bits transfer SCK is in LOW for some time and then starting back. [Refer below picture channel 2 (green) waveform ]
3. SDI line has the same 32bit header, 32 bit data and 32 bit dummy data which I sent from S32K144 MOSI.
4. SDO echoes "0xC000 0000" during header transmission (Ignored data), "0xC000 0001" during both data & dummy data transmission which expected to be header & data as per datasheet.
The header seems to be correct, example I used "0x30000c00" for IMASK0.
So, whether that delay in SCK between each 32 bits makes an issue?


- 新着としてマーク
- ブックマーク
- 購読
- ミュート
- RSS フィードを購読する
- ハイライト
- 印刷
- 不適切なコンテンツを報告
Hi,
a delay in SCK should not be an issue. Check if there are right number of clock periods in words.
To say more capture full frame in scope/analyzer.
I guess you have wrong parity bit calculated. You wrote "The header seems to be correct, example I used "0x30000c00" for IMASK0." But this time parity bit should be set to have odd number of "1" in header.
BR, Petr

- 新着としてマーク
- ブックマーク
- 購読
- ミュート
- RSS フィードを購読する
- ハイライト
- 印刷
- 不適切なコンテンツを報告
Finally its working and the issue is with header as you stated. Actually, I read like we should set the parity bit to "1'" if we have odd number of 1's between bit 31:1 and thus in my case I didnt set it. After your comment I just deep dive into it and got to know that my understanding is wrong. Thanks for lightning up.!
