Need help for SPI FIFO on 56F8037

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

Need help for SPI FIFO on 56F8037

1,642 Views
JerryLe
Contributor I

I set Slave mode in 56F8037, set receive FIFO 2words, transmite FIFO 2words。

 

DSP work into it's Interrupt Service Routine(void SS1_InterruptRx(void)) all the time.

Why? Is there any bug in FIFO control on 56F8037? or my code problem?

 

I modify source from code generated by PE. Code as below:

 

 

void SS1_Init(void)
{
  /* QSPI0_SCTRL: SPR2=0,SPR1=0,SPR0=0,DSO=0,ERRIE=0,MODFEN=0,SPRIE=0,SPMSTR=0,CPOL=1,CPHA=1,SPE=0,SPTIE=0,SPRF=0,OVRF=0,MODF=1,SPTE=0 */
  setReg(QSPI0_SCTRL,0xC2);            /* Set control register */
  /* QSPI0_DSCTRL: WOM=0,??=0,??=0,BD2X=0,SS_IN=0,SS_DATA=0,SS_ODM=0,SS_AUTO=0,SS_DDR=0,SS_STRB=0,SS_OVER=0,??=0,DS3=1,DS2=1,DS1=1,DS0=1 */
  setReg(QSPI0_DSCTRL,0x0F);           /* Set data size and control register */
  /* ??=0, TRWM1=1, TRWM0=0, ??=0, RFWM1=0, RFWM0=1, ??=0, FIFO_ENA=1 */
  setReg(QSPI0_FIFO,0x45);               /* Set FIFO register. ljr.add 2009.3.10 */
  SerFlag = 0;                         /* Reset all flags */
  ErrFlag = 0;                         /* Reset all flags in mirror */
  SS1_EnEvent = FALSE;                 /* Disable events */
  EnUser = FALSE;                      /* Disable device */
  SS1_InpLen = 0;                      /* No char in the receive buffer */
  InpPtrW = InpPtrR = InpBuffer;       /* Set pointer on the first item in the receive buffer */
  SS1_OutLen = 0;                      /* No char in the transmit buffer */
  OutPtrW = OutPtrR = OutBuffer;       /* Set pointer on the first item in the transmit buffer */
  HWEnDi();                            /* Enable/disable device according to the status flags */
  setReg(QSPI0_DXMIT,0xFF);
}
 

 

Interrupt service routine code:

dword dwDataWT[128]={0};
dword dwDataRD[128]={0};
#pragma interrupt alignsp saveall
void SS1_InterruptRx(void)
{
  register word Data1;                  /* Temporary variable for data */
  register word Data2;                  /* Temporary variable for data */

 

  LED3_On();

  getReg(QSPI0_SCTRL);
  if (getRegBit(QSPI0_SCTRL,OVRF))   /* Occured any overflow condition between QSPI0_SCTRL and QSPI0_DRCV reading? */
  {

    LED1_On();

    getReg(QSPI0_DRCV);                /* Clear the overflow flag */
  }
  if (getRegBit(QSPI0_SCTRL,MODF))
  {

    LED1_On();
    setRegBit(QSPI0_SCTRL,MODF);
  }
  if (getRegBit(QSPI0_SCTRL, SPTE))
  {
      LED2_On();
  }
  if (getRegBit(QSPI0_SCTRL,SPRF))
  {
      LED1_On();
    Data1 = getReg(QSPI0_DRCV);           /* Read data from receiver */
    Data2 = getReg(QSPI0_DRCV);           /* Read data from receiver */
    if (Data1&0x8000)//ARM要读DSP的数据
    {
      Data2 = (Data1>>8)&0x007F;
      setReg(QSPI0_DXMIT, (word)(dwDataRD[Data2]>>16));
      setReg(QSPI0_DXMIT, (word)dwDataRD[Data2]);
    }
    else //ARM写数据给DSP
    {
      dwDataWT[Data1>>8] = (dword)Data1<<16+(dword)Data2;
      setReg(QSPI0_DXMIT,0xFFFF);
      setReg(QSPI0_DXMIT,0xFFFF);
    }
  }
  LED3_Off();
  LED2_Off();
  LED1_Off();
}

0 Kudos
Reply
2 Replies

678 Views
JerryLe
Contributor I

after i set interrupt priority to medium priority, and rewrite ISR, it ok now.

but i don't know the reason yet.

 

dword dwDataWT[128]={0};
dword dwDataRD[128]={0};
#pragma interrupt alignsp saveall
void SS1_InterruptRx(void)
{
  register word Data1;                  /* Temporary variable for data */
  register word Data2;                  /* Temporary variable for data */
  register word index;
  LED3_On();
  getReg(QSPI0_SCTRL);                 /* Dummy read the device error register */
  Data1 = getReg(QSPI0_DRCV);                  /* Dummy read data from receiver */
  Data2 = getReg(QSPI0_DRCV);                  /* Dummy read data from receiver */
  if (getRegBit(QSPI0_SCTRL,OVRF)) {   /* Occured any overflow condition between QSPI0_SCTRL and QSPI0_DRCV reading? */
    getReg(QSPI0_DRCV);                /* Clear the overflow flag */
  }
  index = (Data1>>8)&0x007F;
  if (Data1&0x8000)//ARM要读DSP的数据
  {
    setReg(QSPI0_DXMIT, (word)(dwDataRD[index]>>16));
    setReg(QSPI0_DXMIT, (word)dwDataRD[index]);
  }
  else //ARM写数据给DSP
  {
    dwDataWT[index] = Data1;
    dwDataWT[index]<<=16;
    dwDataWT[index]+= Data2;
    setReg(QSPI0_DXMIT,0xFFFF);
    setReg(QSPI0_DXMIT,0xFFFF);
  }
  LED3_Off();
}

 

 

void SS1_Init(void)
{
  /* QSPI0_SCTRL: SPR2=0,SPR1=0,SPR0=0,DSO=0,ERRIE=0,MODFEN=0,SPRIE=0,SPMSTR=0,CPOL=1,CPHA=1,SPE=0,SPTIE=0,SPRF=0,OVRF=0,MODF=1,SPTE=0 */
  setReg(QSPI0_SCTRL,0xC2);            /* Set control register */
  /* QSPI0_DSCTRL: WOM=0,??=0,??=0,BD2X=0,SS_IN=0,SS_DATA=0,SS_ODM=0,SS_AUTO=0,SS_DDR=0,SS_STRB=0,SS_OVER=0,??=0,DS3=1,DS2=1,DS1=1,DS0=1 */
  setReg(QSPI0_DSCTRL,0x0F);           /* Set data size and control register */
  setReg(QSPI0_FIFO,0x45);               /* Set FIFO register. ljr.add 2009.3.10 */
  setRegBit(QSPI0_SCTRL,SPE);          /* Enable device */
  setReg(QSPI0_DXMIT,SS1_EOF);         /* Store the empty char to the transmit register */
  setRegBits(QSPI0_SCTRL,(QSPI0_SCTRL_ERRIE_MASK|QSPI0_SCTRL_SPRIE_MASK)); /* Enable receive and error interrupts */
  /* ??=0, TRWM1=1, TRWM0=0, ??=0, RFWM1=0, RFWM0=1, ??=0, FIFO_ENA=1 */
}
 

0 Kudos
Reply

678 Views
JerryLe
Contributor I

I check LED1/LED2/LED3 status with scope, find DSP work in Interrupt Service Routine, with LED3 always toggle it's status. LED2 and LED1 correct. But I don't know what is the interrupt source.

 

who can give me a hand, thanks all.

0 Kudos
Reply