SPI Communication Issue with TC6 SPI Protocol

キャンセル
次の結果を表示 
表示  限定  | 次の代わりに検索 
もしかして: 

SPI Communication Issue with TC6 SPI Protocol

ソリューションへジャンプ
374件の閲覧回数
Muthappan_Viswanthan
NXP Employee
NXP Employee

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:

Muthappan_Viswanthan_0-1744240393943.png

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!

0 件の賞賛
返信
1 解決策
287件の閲覧回数
PetrS
NXP TechSupport
NXP TechSupport

Hi,

code looks normal, but I think a protocol looks little bit different. There should be 3 words transferred for single register writing/reading

PetrS_0-1744696020470.png

PetrS_1-1744696028761.png

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

 

元の投稿で解決策を見る

9 返答(返信)
120件の閲覧回数
malove
Contributor IV

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.

 

malove_0-1745485549079.png

 

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]

97件の閲覧回数
Muthappan_Viswanthan
NXP Employee
NXP Employee
Thanks for your reply. Rightnow, Iam using older version of S32 DS and doing baremetal programming. But thought of switching to newer version and using RTD, this might helpful for me in that case. Thanks again!
0 件の賞賛
返信
80件の閲覧回数
malove
Contributor IV

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

0 件の賞賛
返信
348件の閲覧回数
PetrS
NXP TechSupport
NXP TechSupport

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

0 件の賞賛
返信
300件の閲覧回数
Muthappan_Viswanthan
NXP Employee
NXP Employee

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:

Muthappan_Viswanthan_0-1744662637917.png

For this purpose I used the below code : 

#include "S32K144.h" /* include peripheral declarations S32K144 */
#define CS_LOW()    (PTB->PCOR = (1 << 5))  // Clear bit to pull CS low
#define CS_HIGH()   (PTB->PSOR = (1 << 5))  // Set bit to pull CS high
 
 
 
//System registers (MMS = 0)
const TC6Reg TC6ADR_RESET      = { .mms = 0x00, .addr = 0x003 };
const TC6Reg TC6ADR_CONFIG0    = {.mms = 0x00, 0x0004};
const TC6Reg TC6ADR_STATUS0    = {.mms = 0x00, 0x0008};
const TC6Reg TC6ADR_IMASK0     = {.mms = 0x00, 0x000C};
const TC6Reg TC6ADR_PLCACTL0   = {.mms = 0x04, 0xCA01};
const TC6Reg TC6ADR_PLCACTL1   = {.mms = 0x04, 0xCA02};
const TC6Reg TC6ADR_PLCASTAT   = {.mms = 0x04, 0xCA03};
const TC6Reg TC6ADR_MAC_NCR    = {.mms = 0x01, 0x0000};
const TC6Reg TC6ADR_MAC_NCFGR  = {.mms = 0x01, 0x0001};
 
uint32_t tx_16bits = 0xFD00FD00;
uint32_t tx_32bits_array[2] = {0xFD00, 0X1010};
uint32_t LPSPI0_16bits_read; /* Returned data in to SPI */
uint16_t lan8650_phy_id = 0;
uint32_t tx_upper = 0xFD00FD00;
uint32_t tx_lower = 0x1010ABCD;
uint32_t rx_upper, rx_lower;
 
// Calculates odd parity for a 32-bit word (excluding bit 0)
uint8_t calculate_parity(uint32_t word31to1) {
   uint8_t count = 0;
   int i;
   for (i = 1; i < 32; i++) {
       if ((word31to1 >> i) & 0x01) count++;
   }
   return (count % 2 == 0) ? 0 : 1;  // Return 0 if even (to make odd)
}
 
uint32_t build_ctrl_header(uint8_t wnr, uint8_t mms, uint16_t addr, uint8_t num_regs) {
   uint32_t header = 0;
   header |= (0U << 31);                 // DNC = 0 (Control)
   header |= (0U << 30);                 // HDRB = 0 (Ignored on write)
   header |= ((wnr & 0x01) << 29);       // WNR: 1 = write, 0 = read
   header |= (0U << 28);                 // AID = 0 (auto-increment)
   header |= ((mms & 0x0F) << 24);       // MMS = memory map select
   header |= ((addr & 0xFFFF) << 8);     // Register address
   header |= ((num_regs & 0x7F) << 1);   // Length (in registers), shifted to [7:1]
   uint8_t parity = calculate_parity(header & 0xFFFFFFFE); // Clear bit 0 for parity calc
   header |= parity; // Set bit 1 to make parity odd
   return header;
}
 
 
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: PCS3, 16 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=3: Transfer using PCS3 */
/* 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 SOSC_init_8MHz(void) {
 SCG->SOSCDIV=0x00000101; /* SOSCDIV1 & SOSCDIV2 =1: divide by 1 */
 SCG->SOSCCFG=0x00000024; /* Range=2: Medium freq (SOSC between 1MHz-8MHz)*/
 /* HGO=0: Config xtal osc for low power */
/* EREFS=1: Input is external XTAL */
 while(SCG->SOSCCSR & SCG_SOSCCSR_LK_MASK); /* Ensure SOSCCSR unlocked */
 SCG->SOSCCSR=0x00000001; /* LK=0: SOSCCSR can be written */
 /* SOSCCMRE=0: OSC CLK monitor IRQ if enabled */
/* SOSCCM=0: OSC CLK monitor disabled */
/* SOSCERCLKEN=0: Sys OSC 3V ERCLK output clk disabled */
/* SOSCLPEN=0: Sys OSC disabled in VLP modes */
/* SOSCSTEN=0: Sys OSC disabled in Stop modes */
/* SOSCEN=1: Enable oscillator */
 while(!(SCG->SOSCCSR & SCG_SOSCCSR_SOSCVLD_MASK)); /* Wait for sys OSC clk valid */
}
void SPLL_init_160MHz(void) {
 while(SCG->SPLLCSR & SCG_SPLLCSR_LK_MASK); /* Ensure SPLLCSR unlocked */
 SCG->SPLLCSR = 0x00000000; /* SPLLEN=0: SPLL is disabled (default) */
 SCG->SPLLDIV = 0x00000302; /* SPLLDIV1 divide by 2; SPLLDIV2 divide by 4 */
 SCG->SPLLCFG = 0x00180000; /* PREDIV=0: Divide SOSC_CLK by 0+1=1 */
 /* MULT=24: Multiply sys pll by 4+24=40 */
/* SPLL_CLK = 8MHz / 1 * 40 / 2 = 160 MHz */
 while(SCG->SPLLCSR & SCG_SPLLCSR_LK_MASK); /* Ensure SPLLCSR unlocked */
 SCG->SPLLCSR = 0x00000001; /* LK=0: SPLLCSR can be written */
 /* SPLLCMRE=0: SPLL CLK monitor IRQ if enabled */
/* SPLLCM=0: SPLL CLK monitor disabled */
/* SPLLSTEN=0: SPLL disabled in Stop modes */
/* SPLLEN=1: Enable SPLL */
 while(!(SCG->SPLLCSR & SCG_SPLLCSR_SPLLVLD_MASK)); /* Wait for SPLL valid */
}
void NormalRUNmode_80MHz (void) { /* Change to normal RUN mode with 8MHz SOSC, 80 MHz PLL*/
 SCG->RCCR=SCG_RCCR_SCS(6) /* PLL as clock source*/
 |SCG_RCCR_DIVCORE(0b01) /* DIVCORE=1, div. by 2: Core clock = 160/2 MHz = 80 MHz*/
 |SCG_RCCR_DIVBUS(0b01) /* DIVBUS=1, div. by 2: bus clock = 40 MHz*/
 |SCG_RCCR_DIVSLOW(0b10); /* DIVSLOW=2, div. by 3: SCG slow, flash clock= 26 2/3 MHz*/
 while (((SCG->CSR & SCG_CSR_SCS_MASK) >> SCG_CSR_SCS_SHIFT ) != 6) {}
 /* Wait for sys clk src=SPLL */
}
 /* TXWATER=3: Tx flags set when Tx FIFO <= 3 */
 
 
void WDOG_disable (void){
 WDOG->CNT=0xD928C520; /*Unlock watchdog*/
 WDOG->TOVAL=0x0000FFFF; /*Maximum timeout value*/
 WDOG->CS = 0x00002100; /*Disable watchdog*/
}
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);
PORTB->PCR[5] |= PORT_PCR_MUX(1);
PTB->PDDR |= (1<<5);
PTB->PSOR |= (1<<5);
 
 
}
 
void lan8650_write_reset(void) {
   uint32_t header = build_ctrl_header(1, 0x00, 0x0003, 0); // Write to RESET reg
   CS_LOW();
   LPSPI0_tx_32bits(header); (void)LPSPI0_rx_32bits();     // Write header
   LPSPI0_tx_32bits(0x00000001); (void)LPSPI0_rx_32bits(); // Write data
   CS_HIGH();
}
void lan8650_write_imask0(uint32_t value) {
   uint32_t header = build_ctrl_header(1, 0x00, 0x000C, 0);
   CS_LOW();
   LPSPI0_tx_32bits(header); (void)LPSPI0_rx_32bits();
   LPSPI0_tx_32bits(value);  (void)LPSPI0_rx_32bits();
   CS_HIGH();
}
uint32_t lan8650_read_imask0(void) {
   uint32_t header = build_ctrl_header(0, 0x00, 0x000C, 0);
   uint32_t data = 0;
   CS_LOW();
   LPSPI0_tx_32bits(header); (void)LPSPI0_rx_32bits(); // Send header
   LPSPI0_tx_32bits(0x00000000);                       // Dummy to clock data
   data = LPSPI0_rx_32bits();                          // Get data
   CS_HIGH();
   return data;
}
 
 
int main(void) {
 
    uint32_t imask_read_value;
    volatile int i;
 
    // Usual system and SPI setup
 
    WDOG_disable();
 
    SOSC_init_8MHz();
 
    SPLL_init_160MHz();
 
    NormalRUNmode_80MHz();
 
    PORT_init();           // Configure SPI pins
 
    LPSPI0_init_master();  // Init LPSPI master
 
    // Small delay before starting (optional)
 
    for ( i = 0; i < 100000; i++); // Optional delay
 
        // Write RESET
 
        lan8650_write_reset();
 
        // Optional delay to allow reset to complete
 
        for ( i = 0; i < 100000; i++);
 
        // Unmask all interrupts
 
        lan8650_write_imask0(0x00000000);
 
        // Read IMASK0 to verify
 
        imask_read_value = lan8650_read_imask0();
 
        // Set breakpoint here to inspect imask_read_value
 
        while (1) { }
 
    return 0;
 
}


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.

Muthappan_Viswanthan_1-1744663056405.png

 

Muthappan_Viswanthan_4-1744663312231.png

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.

 

 

 

0 件の賞賛
返信
288件の閲覧回数
PetrS
NXP TechSupport
NXP TechSupport

Hi,

code looks normal, but I think a protocol looks little bit different. There should be 3 words transferred for single register writing/reading

PetrS_0-1744696020470.png

PetrS_1-1744696028761.png

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

 

186件の閲覧回数
Muthappan_Viswanthan
NXP Employee
NXP Employee

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?

 

0 件の賞賛
返信
139件の閲覧回数
PetrS
NXP TechSupport
NXP TechSupport

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

104件の閲覧回数
Muthappan_Viswanthan
NXP Employee
NXP Employee
Hi,
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.!
0 件の賞賛
返信