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.

MSP430FR59941: eUSCI software reset

Part Number: MSP430FR59941


I'm looking at the datasheet and wondering where I can find info about the software reset of the eUSCI module.

Register: UCBxCRLW0, bit 1: UCSWRST

How long must the peripherial be held in reset to reset the module?

Where is this info located?

Thank you

  • Hello,

    The User's Guide can provide information on the UCSWRST bit. The use case is to have it in the reset state when setting certain bits in your peripheral then setting it 0 to release for operation. There isn't a set amount of clock cycles or time it needs to be held.

    Regards,

    Luke

  • Hello Luke,

    "There isn't a set amount of clock cycles or time it needs to be held."

    Based on what?  Say's who/what?

    Regards,

    a

  • Let me elaborate,..

    I understand there are some settings that should only be made while the eUSCI is not running.  But I have not seen anywhere that say's the reset condition must be held for X amount of time.  But,....

    When I use reset and unreset back to back, I am seeing the clock-line free-run with pulses, and no data-line action.  Clearly the eUSCI is not in a stable state.

    Regards,

    a

  • Hi A,

    What's the context you're resetting the eUSCI for? Are you just trying to change some settings or are you changing the mode into a different communication interface?

    We don't list any info on how long it takes for all the registers to reset.

    Regards,

    Luke

  • The action is to immediatly stop any and all I2C traffic.  Resetting the master will/should stop the clock, halting all traffic. 

    What I am seeing is,... when I pull the master out of reset,... I etither get a clock that clicks for ~350mSec, or I get a leftover I2c device address transmitted.  Neither of these should happen.  reset: IFG is cleared,... IE is cleared

    So,... I'm wondering why the eUSCI is doing this?

    Regards,

    a

  • Hi A,

    I looked at our example code and did some modifications to reset the UCB2 but didn't see any left over signals. Can you send code snippets for the context of when you're resetting the USCI? 

    Regards,

    Luke

  • Hello Luke,

    The problem occurs when the I2C traffic fails.  I'll suggest what you are using does not experience this problem, so you don't see the leftover action.  When the traffic is propper, there is no reset failure/issue.  The reset always happens.  It is basically there to correct a hung bus issue.  The hung bus goes away, but is replaced by unwanted Tx activity, which trashes the next transmission (the receiver is now seeing garbage comm activity.)

    I've tried to attach a couple trace images, but I have never been able to get your site to cooperate.  Thus, I am unable to show you what I am seeing.

    Details of the problem: Typically the failure is a hung bus.  It typically looks like the first bit is lost (never transmitted) and then the byte never gets ACK/NACK (because the bit count is off).  I'm unsure what is causing the bit to be lost.  It is also possible that the first bit is transmitted, but this would mean the prior bytes ACK bit is never sent/seen.  If true, then the problem byte should have never been sent.

    What I was using to reset the eUSCI:    (bash it upside the head once)

      *ucbxctlw0 |= UCSWRST__ENABLE;   // USCI in software reset
    //does not help  clock->DelayMilliseconds(10);
      rxBuff->Clear();    // flush buffers
      txBuff->Clear();
      *ucbxctlw0 &= ~UCSWRST__ENABLE;  // Take out of software reset

    What I am now using:    (bash it upside the head twice)

      *ucbxctlw0 |= UCSWRST__ENABLE;   // USCI in software reset
    //does not help  clock->DelayMilliseconds(10);
      rxBuff->Clear();    // flush buffers
      txBuff->Clear();
      *ucbxctlw0 &= ~UCSWRST__ENABLE;  // Take out of software reset
      *ucbxctlw0 |= UCSWRST__ENABLE;   // USCI in software reset
      *ucbxctlw0 &= ~UCSWRST__ENABLE;  // Take out of software reset

    The first approach showed much leftover comm-action.

    The second approach shows much less, but there is still random leftover comm-action.

    Regards,

    a

  • void I2cSlaveB0::ISR() {
    __disable_interrupt(); // disable global interrupts  GIE= 0
      switch(__even_in_range(UCB0IV, UCIV__UCBIT9IFG))   
      { // highest priority
        case UCIV__UCNACKIFG:           // Vector 0x04
            UCB0IV= 0;  // clear all pending ints
            numRxBytesLeft= 0;
            numTxBytesLeft= 0;
            rxBuff->Clear();    // flush buffers
            txBuff->Clear();
          break;

        case UCIV__UCSTTIFG:            // Vector 0x06
          UCB0IE &= ~UCSTTIE_1;   
          if (UCB0CTLW0 & UCTR)  
            UCB0IE |= UCTXIE0_1;  
          else  {                 
            numRxBytesLeft = 0;   
            numTxBytesLeft = 0;   
            UCB0IE |= UCRXIE0_1;  
          }
          break;  

        case UCIV__UCSTPIFG:            // Vector 0x08
          if (UCB0CTLW0 & UCTR) {
            txBuff->Clear();
            UCB0IFG &= ~ UCTXIFG0;  
          }
          UCB0IE &= ~UCSTPIE_1;  
          UCB0IE |= UCSTTIE_1;   
          break;

        case UCIV__UCRXIFG0:          // Vector 0x16
          unsigned char rxData = UCB0RXBUF;       
          rxBuff->Insert(rxData);          
          // do some stuff with the rx data, format the tx data

          // when last byte for this tx has been received       
            UCB0IE &= ~UCRXIE0_1;  
            UCB0IE |= UCSTTIE_1;  
          }
          break;

        case UCIV__UCTXIFG0:          // Vector 0x18
          if (!txBuff->IsEmpty()) {
            unsigned char tx = txBuff->Remove();          
            UCB0TXBUF = tx;         
            if (!(--numTxBytesLeft)) {    // done yet?
              UCB0IE &= ~UCTXIE0_1;  
              UCB0IE |= UCSTTIE_1;  
            }
          }
          break;

        case UCIV__UCCLTOIFG:         // Vector 0x1c
          i2cClkLoTimeOutErrFlag= true;
          break;
                          
        default:
          break;
      }
    __enable_interrupt();
    }

  • The reset code is on the master device.

    The ISR code is the slave device.

  • Hi A,

    For me when attaching images I have to do insert and can only input one image at a time, most of the time I can copy and paste screenshots as well.

    Can you put a break point when you do the  *ucbxctlw0 |= UCSWRST__ENABLE; ? Once here check the registers on register view and they should reset to 0. Step through your clears and verify that the buffers are getting cleared. With the eUSCI in reset and you clearing the buffers I wouldn't expect any left over byte to be sent. After you verify the buffers and registers are cleared run the program and see if the "trash" data gets sent again.

    If the trash data does get sent I would see if it is actually coming from the target device.

    I would be interested if you are in the middle of receiving data from the target device when you reset the I2C controller device. It should eventually resolve itself but that would be a reason you see trash data.

    Regards,

    Luke

  • I've had some success with clearing/setting the PSEL bits (SCL first/last) around the SWRST. The bus can get hung for any number of reasons, so it's a messy business.

    Unsolicited:

    (1) I've become quite wary of using STPIFG in a Slave, since it may be presented ahead of other state (notably RXIFG) that came first. Also, in the case of a repeated-Start there is no Stop.

    (2) I recommend you not enable interrupts in an ISR. The hardware will put GIE back when the ISR returns.

  • This is the fuil view of the issue.  The left side shows the bus getting hung.  The right side shows the "extra" leftover activity that is the problem.

  • This is a closer look at the left side.  It shows the bus getting hung due to missing ACK/NAK.  The 0x45 is actually a Read on device 0x22,... missign the ACK.  I have been chasing this for a while now.  I find Bruce's comments to be interesting.  (More later)

  • This is a closer look at the right side.  It shows the leftover "extra" traffic.  The SWRST happens when the green line goes high,... basically when the "extra" activity starts.

  • I added the buffer flush calls in the middle of the SWRST on and off,... in hopes the HW would complete its reset during this time.  The buffer-flush should not matter for the I2C traffic as the SWRST clears the InterruptEnable and the IFG registers.  i.e. W/o the IE enabled,... there should be no interrupt requests coming from the eUSCI.  But the image shows there is still something in the pipeline.  The clock can only come from the master,.. so the issue lies there.

    It is rather hard for me to use the debugger as it slows down the process.  i.e. I get different behavior with and w/o the debugger.  Keep in mind that when I halt the processor, it does NOT halt the eUSCI.  Let me try your "snoop at SWRST suggestion.

  • This (middle) trace shows a normal complete Write transaction, followed by a Read where someone is stretching the clock. Since it's a Read, it's probably the Slave ignoring its TXIFG [Ref UG (SLAU367P) Fig 32-9, top left "bus stalled"].

  • YEs, I understand this.  This is one of the big issues I'm having with the slave ISR.  That is,... (Sometimes) During the slave Tx process it will complete and grab the following Rx request all in the same ISR cycle.  That is the IFG = 0x0F (STT, STP, Rx, TX) rather than the expected 0x0A (STP, Tx).  The STT has a higher priority than the STP,... just like the Rx has a higher priority than the Tx,... so the Rx gets services while the Tx does not.  i.e. The Tx buffer never gets data,.... so it stalls.  (That is another problem.)

  • Comments:

    I did service the STP in the ISR, but found it to be troublesome, so I removed it.  This help a bit but now I have the IFG=0x0F issue.  i.e. I'm not able to step through the states: STT Rx STP,... STT, TX, STP,..

    I do have a NACK in the ISR, but it never gets a hit.  I find this odd.  The NACK as the end of a Tx cycle does not trigger it.  I don't see why it would not.

  • Bruce,

    "I recommend you not enable interrupts in an ISR. The hardware will put GIE back when the ISR returns."

    I'm not seeing this is the Users Guide. 

    I see some code that makes use of __bis_SR_register(GIE), but I've never been able to locate guidance on how to use this.  I see an ISR with __bis_SR_register(GIE) but there is no mention of __bic or disable_Interrupts,... so why would you need __bis?  Is this "how to use"  __bis/__bic documented anywhere?

    Where is the info on "hardware will put GIE back when the ISR returns."?

    Thanks

  • It seems odd that you would have both TXIFG and RXIFG set, since for a given transaction you will only see TXIFG (Slave Transmitter) or RXIFG (Slave Receiver). (I suspect one of those is left over from a previous transaction.) One consequence of this is that it might be reasonable to always leave both RXIE and TXIE set, since the IFG tells you what to do.

    I notice that for a TXIFG, if you don't have anything to send, you don't send anything (write TXBUF) at all. I don't think [based on Fig 32-9 and Sec 32.3.7.2] that this is one of your options. If you've run out of data, send filler bytes, but you need to send something to manage the flow control. (It's not uncommon for Masters to accidentally read or write one-too-many bytes.) You always read RXBUF on an RXIFG, but that assumes that RXIE is set at the appropriate time.

    [Edit: Fixed typo.]

  • The interrupt sequence, including saving/restoring the SR (containing GIE), is described in UG Sec 1.3.4.

    enable_interrupt and disable_interrupt are wrappers around __bi[s|c]_SR_register(GIE), but there's a NOP in one of them to handle Sec 1.3.4 ("NOTE").

  • I see many of these unknown-stalls.  They happen randomly.  I can't attribute them to to the ISR execution, but they occur during the ISR execution.  My guess is they are from NMI action.  Maybe watchdog service.  Does anyone else see these?  (I wonder if it may be a hidden issue on my part.)

  • It's a little hard to parse this trace, but it looks as though one side or the other (occasionally) isn't servicing its interrupts in a timely fashion. Clock-stretching isn't intrinsically bad, though generally less is better than more. What else is your code doing? Do you disable interrupts anywhere?

    Unless your code is doing something with the NMI or the Watchdog, I would expect either of these to hang/reset your system and not recover, so those seem unlikely causes.

  • Luke,

    I have verified that SWRST action.  The eUSCI reg's do clear.  I do still get the "extra" traffic when the prior I2C traffic hang the bus.  i.e. This "extra" traffic seems to only occur when the bus gets hung.  (But that is the whole reason for the SWRST action,... to recover a hung bus.)  Here is a trace of the "endless" CLK that I mentioned earlier.  After the SWRST (at the falling white trace) it bangs away for ~340mSec.

  • Bruce,

    I do believe you are correct.  The stall always appears at the ACK.  I only see it when the slave is in Tx transaction.  i.e. The master is slow to ACK.  I'm just trying to understand where it is coming from.  (I don't believe this is a problem.)

    After reviewing the UG 1.3.4.1 & 1.3.4.2, I removed both the enable and disable interrupt calls inside the ISR.  I see no unexplained difference in ISR operation.  This makes me question the __bis_SR_register(GIE) calls I saw in other posted code examples.  And I finally see where the GIE=0 is coming from.  Thank you

    I've had some success with clearing/setting the PSEL bits (SCL first/last) around the SWRST.

    Can you elaborate?  I'm guessing you are unselecting the eUSCI then doing the SWRST action then re-selecting the eUSCI.  Basically isolationg the peripheral from the pins during the SWRST.  This seems like a solution for the single "extra" byte problem.  But I doubt it will work for the "endless" CLK issue.

  • If you've run out of data, send filler bytes

    I'm puzzled by this.  I have seen code that does pad extra bytes into the Tx.  It seemed like a mistake to me, as, how would the listener know if they (extra bytes) were part of the real response or not.  Or, how would the listener know the payload now needs to to be increased by one?  It seems like a better apporach would be to cancel the transaction and start over again.  So why bother trying to add extra bytes?  (Just a waste of time.)

  • I have seen this "eternal Stop" (also an "eternal Start") symptom from time to time, always when I was doing something unusual on the bus. I suspect it has to do with the bus monitor somehow not seeing the SDA transition (even though we can see it right there).

    I saw it when I was testing my bus-hang reset code, and as I recall (it was some time ago) it cleared up when I changed the PSEL release to let SCL go first, then SDA. I suspected at the time that it had to do with creating something that looked vaguely like a Stop condition. (I don't know the inner workings of the EUSCI.)

    Do both sides reset themselves on a bus timeout?

  • how would the listener know if they (extra bytes) were part of the real response or not

    How does the Slave know how much data the Master wants?

    The Slave doesn't have much control over the bus -- it doesn't control the clock (signal) or the SLA or (for a Slave-Transmitter) the ACK cycle, and it can't Stop the transaction. The only control it has is to hold SCL low (stretching the clock), but this isn't very useful since it's already used to mean "wait just a moment".

    So if the Master asks the Slave for data after the Slave thinks it has run out, the only choices are (a) provide some (dummy) data or (b) hang the bus. 

  • Do both sides reset themselves on a bus timeout?

    The master gets the SWRST and unSWRST.  The device gets disconnected from the bus with HW.

    How does the Slave know how much data the Master wants?

    Both the master and slave are aware of the # of bytes incomming and outgoing.  (The protocol is fixed.)      I was wondering how to recover from an added byte in the middle of a response, not only at the end.  (As you suggest.)

    I'm getting the impression that I am not doing anything improper in the code.  This is just how the HW works.  I will need to find a way around these peculiarities.

    Thank you for the insight

  • For what it's worth, the I2C people considered the ("unlikely") problem of a Slave stuck while holding SCL low. They suggest an out-of-band mechanism  (Reset or Power control wire to the Slave) to clear the bus [Ref I2C spec (UM10204 Rev 6) Sec 3.1.16].

**Attention** This is a public forum