This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Spi Rx flag is not reset.

Other Parts Discussed in Thread: MSP430F5438A

hello,

 

i'm working with msp430f5438A,

ccs 5.3 compiler version: 4.1

implement spi in UCB0.

 

my question is relating the spi.

i write to fram via spi communication.

For some unknown reason , in the following function , although that I reset the rx flag ( UCRXIFG) . the flag is not reset in the code (non-stop running), and the code reach the function :FramWrSingle() , when the RxFlag is still set.

But if I run the code step by step ( with debugger) or mount breakpoint before and after the while loop that reset the flag .

then the code work correct and the Rx flag is reset.

 

maybe  it compiler problem, i'm not sure..

Is anyone have an idea what is the problem?

 

Thanks.

Asher.

-----the code

volatile Uint8 fakedata;

volatile Uint32 PcRegister;

#define CLEAR_SPI_RX_FLAGS()  UCB0IFG &=~UCRXIFG;

Flag_t FrmFillData (FramAdrss_t StartAddress, Uint32 size, Uint8 Data)

{

            unsigned long tmp = size;

            Flag_t res = TRUE;

     CLEAR_SPI_RX_FLAGS();

            FramWrSingle(FRAM_WRITE);

            FrmSetAddress ( (FramAdrss_t)StartAddress);// write setting: address & opcode

            //FramWrBlock (&SrcBuff[0], TransSize ); // write block of data.

            __delay_cycles(100);

            while (tmp--)

            {

 

                       while ((UCB0IFG&=UCRXIFG)!=0)

                       {

                                    UCB0IFG = 0;

                                    fakedata = UCB0RXBUF;

                                    CLEAR_SPI_RX_FLAGS();

                       }

                       res = FramWrSingle( Data);

                       if (res == FALSE)

                       {

                                    break;

                       }

            }

            return res;

}

 

Summary of flags set:

Compiler

-vmspx --abi=eabi --code_model=small --data_model=small -Ooff -g --include_path="C:/ti/ccsv5/ccs_base/msp430/include" --include_path="C:/ti/ccsv5/tools/compiler/msp430_4.1.2/include" --include_path="../hal" --include_path="../hdr" --advice:power="all" --define=__MSP430F5438A__ --define=PD_EV_BRD --diag_warning=225 --display_error_number --diag_wrap=off --silicon_errata=CPU21 --silicon_errata=CPU22 --silicon_errata=CPU23 --silicon_errata=CPU40

Linker:

-vmspx --abi=eabi --code_model=small --data_model=small -Ooff -g --advice:power="all" --define=__MSP430F5438A__ --define=PD_EV_BRD --diag_warning=225 --display_error_number --diag_wrap=off --silicon_errata=CPU21 --silicon_errata=CPU22 --silicon_errata=CPU23 --silicon_errata=CPU40 -z --stack_size=400 -m"BlkAtp.map" --heap_size=400 --use_hw_mpy=F5 -i"C:/ti/ccsv5/ccs_base/msp430/include" -i"C:/ti/ccsv5/tools/compiler/msp430_4.1.2/lib" -i"C:/ti/ccsv5/tools/compiler/msp430_4.1.2/include" --reread_libs --warn_sections --display_error_number --diag_wrap=off --rom_model

 

  • Just out of curiosity - what are you trying to accomplish? You say you are using MSP4305438A device, but are trying to write to FRAM. That device is a Flash-based part and does not have any FRAM in it.
  • I using FRAM to save data.
    i communicate with the fram via spi.
    the fram component is FM25V20,
    but the fram is not the problem .
    the msp or the compiler is the issue.
  • So you are trying to write to an external FRAM chip using the SPI interface.

    You say that the FRAM chip is not the problem, and that may very well be. But, by describing your setup and providing the additional details, you help others understand the conceptual picture of your setup and what you are specifically trying to accomplish.

    You didn't provide any detail on how you are configuring the peripheral nor how you arrive at the function you provided. The flag should be automatically reset for you when you read the UCB0IV register in your ISR. But it looks like one big polling loop....

    So let me ask this... why do you care the value of UCB0RXIFG? You don't seem to be reading any of the data back, just writing bytes out to the part. Ignore the reading of the rxbuf and checking of RXIFG altogether. If you don't read, the byte just gets overwritten by the next set of bits that you also don't use.
  • Hello,

    my spi set up is bellow.
    the msp is master ( the only master) and the external fram
    is the only slave.

    the infinite while loop is to debug the problem . just to
    illustrate the fact that the Rx flag is not reset, although
    all the action that i take ( like read the Rx buffer, or
     reset the flag).

    the problem exist also in the reading routine:

    volatile Uint8 fakedata;
    Flag_t FramRdCmp (FramAdrss_t StartAddress, Uint32 size, Uint8 ExpectedData)
    {
           Uint32 tmp = 0; //
           Flag_t res = TRUE;
           Uint8 dumyData = 0x00;
           CLEAR_SPI_RX_FLAGS();
           FramWrSingle(FRAM_READ);
           FrmSetAddress ( (FramAdrss_t)StartAddress);// write setting: address & opcode
    //       UCB0IFG &=~UCRXIFG;// clear all previous flags
           while (tmp < size )// read the whole fram data.
           {
                  while ((UCB0IFG&=UCRXIFG)!=0)// the while loop is for debug.
                  {
                      UCB0IFG = 0;
                      fakedata = UCB0RXBUF;
                      CLEAR_SPI_RX_FLAGS();
                  }

               __delay_cycles(100);
               frmBuf[tmp] = FramRdSingle(dumyData);
               tmp++;
    //           if (framDataRd != ExpectedData)
    //           {
    //               res = FALSE;
    //               break;
    //           }

           }
           return res;
    }

    so,the fact that the Rx data is not reset
    couse problem .
    the msp read more extra byte that is not realy exist
    ( if i check the communication by scope i can see the
    there is no extra data that arrive from the fram).

    void SpiMasterCnfg (void)
    {
         UCB0CTL1 |= UCSWRST;             
          UCB0CTL0 |= UCMST+UCSYNC+UCMSB;
          UCB0CTL0|= UCCKPL  ;

          UCB0CTL1 |= UCSSEL_2;                     // SMCLK

         //Bit clock prescaler low byte. The 16-bit value of (UCBxBR0 + UCBxBR1 × 256)
          UCB0BR0 = 66;        // /16M/64 = 250K bit rate
          UCB0BR1 = 0;
        
          UCB0CTL1 &= ~UCSWRST;         // **Initialize USCI state machine**


    }

  • Hello,

     

    I want to illustrate the problem.

    In the following code, when the I use the functions SpiBSnd() and SpiRd(),

    and I check the flag UCB0IFG.UCRXIFG (Rx flag) after the SpiRd().

    the result supposed to be that Rxflg is clear. And it really is.

    ----

    OPEN_FRAM();

    SpiBSnd(0x06);// write.

    Fdbgdata = SpiRd();// read data;

    CLOSE_FRAM();

    __delay_cycles ( CYCLES_DELAY_1US(10));// if I check the rx flag here it’s clear.

    ---

    But in the case that I write number of time (suppose that I want to write an address and I don’t have to wait for data ) although that I reset the Rxflag, the flag is still set after I read data.

    --

    OPEN_FRAM();

    SpiBSnd(0x06);// write.

    SpiBSnd(0x07);// write.

    SpiBSnd(0x08);// write.

    SpiBSnd(0x09);// write.

    CLEAR_SPI_RX_FLAGS();

    Fdbgdata = SpiRd();// read data;

    CLOSE_FRAM();

    __delay_cycles ( CYCLES_DELAY_1US(10));// if i check the Rx flag here it still set...

     

    The problem in that situation is that the data I read is not the data that I see when I use the scope,

    Wrong flag causes I read the wrong information.

     

    Asher.

    -------------------

    More helpful data:

    #define CLEAR_SPI_RX_FLAGS()      UCB0IFG &=~UCRXIFG;// clear Rx flag

    #define FRAM_CS_SU 1

    #define FRAMCS_TRNS_START __delay_cycles(FRAM_CS_SU); P3OUT &= ~BIT0;__delay_cycles(FRAM_CS_SU);

    #define FRAMCS_TRNS_END __delay_cycles(FRAM_CS_HOLD);P3OUT |=0x01;

     

    #define OPEN_FRAM()             FRAMCS_TRNS_START

    #define CLOSE_FRAM()          SpiWaitEndTx(); FRAMCS_TRNS_END;

     

    Configuration function:

    void SpiMasterCnfg (void)

    {

           UCB0CTL1 |= UCSWRST;             // **Put state machine in reset**

           UCB0CTL0 |= UCMST+UCSYNC+UCMSB; // 3-pin, 8-bit SPI master

           UCB0CTL0|= UCCKPL ;

           UCB0CTL1 |= UCSSEL_2;// SMCLK

           UCB0BR0 = 0;// up to the mclk..

           UCB0BR1 = 0;                            

           UCB0CTL1 &= ~UCSWRST; // **Initialize USCI state machine**

     

    }

    Read and write function

    Flag_t SpiBSnd(Uint8 data)

    {

           Uint16 SpiWatchCounter = 2* CYCLES_PER_SPI_SEND_CHAR;// take factor of 2

           while (((UCB0IFG&UCTXIFG)==0)&& (--SpiWatchCounter));//wait here, USCI_B0 TX buffer ready?

           if (SpiWatchCounter==0)// then error

           {

                  SpiErrNum = SET;

           }

           UCB0TXBUF = data;// Send value

           return OK;

    }

     

     

    Uint16 SpiRd (void)

    {

           Uint16 volatile data;

           Uint16 volatile data2;

           Uint16 SpiWatchCounter = 2* CYCLES_PER_SPI_SEND_CHAR;// take factor of 2

           while (((UCB0IFG&UCRXIFG)==0)&& (--SpiWatchCounter));/*wait here,

           * USCI_B0 TX buffer ready?

           */

           _no_operation();// for debugging.

           if (SpiWatchCounter==0)// then error

           {

                  SpiErrNum = SET;

                  return 0xFE;

           }

     

           else       {

                  data = UCB0RXBUF;

                  return data;

           }

  • I haven't seen this precise symptom before, but my guess is that it has to do with overrun (UCOE), a condition which you are certainly triggering.

    Try clearing the IFG by reading RXBUF, rather than clearing the IFG bit directly. I make a point to always do it this way (which may be why I've never seen this symptom).

  • Hello,

    1. of course that the over run flag is set when I write several times and not read the data. But what all of this have to do with the fact that the Rxflag is not clear ( in free running, in case that I run step by step the bit is clear).?
    2. There is no reminder in the user guide (slau208n.pdf) that this is the ONLY way ( by reading the  RXBUFF) to reset RXIFG and that I can not use to clear the RXFLG by simply clear the Rx flag bit.
    3. if the way to reset the OVER_RUN flag is to read  the RxBUFFER ? Not always one reading is enough (in case that I write severat times, need to read the buffer twice in order to reset the Overrun flag, try it) . So how much reading I need to do? Where it is defined?
    4. The fact that the RXFlag is not reset even though I reset it by command ( clear the bit ) . Is it a problem of hardware or software (compiler)?
    5. why there is difference in the behave of the flags ( Rxflag and Overrun flag) between free running code and to step by step ( debugging) ?.       when I run step by step ( debug) the RxFlags is reset by command ( simply clear the correct bit       of  the RX flag) and the overrun flag is reset after one reading of RXBUFFER,Why it’s not behave the same in free running code
    6. try to play with that following code, place the break-point in different places, check the difference between free running and to step by step, check when RxFlg and overrun flag when it set or clear , how it behave?.

     

    While ( 1){

          OPEN_FRAM();

          SpiBSnd(0x06);// write opcode or dummy data.

          SpiBSnd(0x07);// write opcode or dummy data.

          SpiBSnd(0x08);// write opcode or dummy data.

          SpiBSnd(0x09);// write opcode or dummy data.

          SpiBSnd(0x0A);// write opcode or dummy data.

          SpiBSnd(0x0B);// write opcode or dummy data.

          SpiBSnd(0x0C);// write opcode or dummy data.

          CLEAR_SPI_RX_FLAGS();

          Fdbgdata = SpiRd();// read data;

          Fdbgdata = UCB0RXBUF;

          Fdbgdata = UCB0RXBUF;

          CLOSE_FRAM();

          __delay_cycles ( CYCLES_DELAY_1US(10));

    }

    6. therefore , I can draw the conclusion, that the way to deal with the SPI is to make ALWAYS pairs of operations ( writing and reading) Although sometimes I just want to write and not need to read. Is this true?
    So why even this is not defined in the CPU literature ?

    Thanks.

     

     

     

     

     

  • You run the SPI at MCLK speed. That means you have only 8 MCLK cycles per byte. So when you write to TXBUF, you only have 8 MCLK cycles until RXIFG is set again. How many clock cycles does your code take, what do you think?
    When operating the SPI at MCLK speed, then you need precisely timed assembly code to get max throughput, else the USCI is always waiting for the CPU. And if you do, you don't care for interrupt flags at all.
  • >When operating the SPI at MCLK speed, then you need precisely timed assembly code to get max throughput, else the USCI is always waiting for the CPU. And if you do, you don't care for interrupt flags at all.

    Or you could use the DMA engine.
  • Yes and no. On the new eUSCI, DMA isn't always working. Also, DMA timing depends on the current CPU instruction. And setting up DMA is sometimes more overhead that you save. :)
    But finally, if someone hasn't mastered the 'normal way' first, how is he supposed to master DMA and avoid the pitfalls?

**Attention** This is a public forum