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.

CPUOFF every other LPM3_EXIT

Here's one for one of the experts out there: Simple buffering up a received message and transmitting it back out. Debugging revealed --

If my buffer had an even number of characters in it (excluding the end null) I would transmit just fine because the CPU was on after returning from

the interrupt with the flag == 1.  If it had an odd number of characters in it and the flag == 1 the CPU was off after the return, but only every other time.  Honest.

The number of characters didn't matter.  Nothing else is running in this simple application. What am I missing?

The terminal window looked like this for even number of chars:

123'\r'   (sent via RS232)

123     returned from 430

123'\r'  (sent via RS232)

123     returned from 430

For odd number of chars:

12'\r'   (sent via RS232)

12'\r'  (sent via RS232)

12     returned from 430


Here's the basic code:

 

char Message_buffer[BUFF_SIZE];
char ct1 = 0;

int main( void )
{

  WDTCTL = WDTPW + WDTHOLD;    //Stop watchdog timer to prevent time out reset

  Init();                      //Initialize the I/O ports & UART
  Uart_init();

  BCSCTL1 = CALBC1_1MHZ;                    // Set DCO
  DCOCTL = CALDCO_1MHZ;
  BCSCTL3 = LFXT1S_2;          //Use VLOCLK for ACLK

  _BIS_SR(GIE);                //Enable non-maskable interrupts

  while(1)
  {

    _BIS_SR(LPM3 + GIE);         //go to sleep until character is received

__no_operation();

if(send_flag == 1)

{

 
// transmit_the_buffer

}
}

#pragma vector=USCIAB0RX_VECTOR
__interrupt void USCI0RX_ISR(void)
{

  Message_buffer[ct1++] = UCA0RXBUF;

//if CR or buffer full, send the message

  if((Message_buffer[ct1 - 1] == '\r') || (ct1 == BUFF_SIZE))
  {
    Message_buffer[ct1] = '\0';
    ct1 = 0;
     flag = 1;

  }

LPM3_EXIT;
}

  • I guess oyu left out important parts of the code.
    In the part you posted, you receive bytes into a buffer, but then you never do anything with them.

    Some comments anyway:

    1) You use send_flag and flag. I guess flag shall be receive_flag?

    2) if (ct1==BUFF_SIZE) Message_buffer[ct1] = \0;
    this (possible case extracted form your code) will write behind Message_buffer (array out-of-bounds).The index must be in the range [0..(BUFF_SIZE-1)] yet ct1 is BUFF_SIZE in this case.

    3) you always return from LPM3 once a byte is received. If you don't do anything with the buffer and wait for flag==1 before you proceed, why not moving LPM3_EXIT into the IF statement and exiting LPM only if the buffer has been filled completely?

  • When the buffer is full I set "send_flag" to indicate that it's time to send. It's only a name and I could have called it Irving.

    From the original post and the terminal display examples it is obvious that I echo the buffer.

    To get around the mysterious behavior I moved the transmit code to the ISR, which worked correctly every time. Since there is nothing else what so ever going on, this works,

    but doesn't answer the original question.

  • eltury said:
    When the buffer is full I set "send_flag" to indicate that it's time to send. It's only a name and I could have called it Irving.


    No, when the buffer is full, you set 'flag'. Yet you never test for 'flag', you test for 'send_flag', hence my question whether 'flag' is rather 'receive_flag' or what else. if 'flag' == 'send_flag', well, did you tell the compiler? At least you didn't tell us.

    eltury said:
    From the original post and the terminal display examples it is obvious that I echo the buffer.

    It's obvious that you WANT to echo the buffer, yet you don't show how you try to do it.
    If everything is obvious, why is there a problem? If code would alwas do what you want it to do, there would be no need for debugging.
    With the crippled code you posted, there may or may not a problem in this or any other part of the code. usually, the problem is how different parts of the code interact. And you cannot analyze it if you don't see half of these parts.

    It's not what you want it to do and it's not what you tell it to do, it's the difference between want you want it to do and what you tell it to do.

  • Yeah, well, sorry for the typo. flag = send_flag.

    I basically gave screen shots in my OP. That should tell anyone that I echoed the buffer. But that's beside the point.

    Whether I send the buffer back out or throw it away is irrelevant to the problem. The sleeping CPU issue occurs before I even attempt to call the TX routine. The

    issue is why the CPU doesn't always wake from the LPM3 mode when asked to do so.

  • eltury said:
    The sleeping CPU issue occurs before I even attempt to call the TX routine.

    Well, I tried to figure out why you have problems with an odd number of characters and didn't notice that it was the CPU being on or off that really concerns you.

    eltury said:
    issue is why the CPU doesn't always wake from the LPM3 mode when asked to do so.

    That's probably because you look at the CPU at the wrong moment.

    If you place a breakpoint on the __no_operation after entering LPM, this will cause a break BEFORE the CPU enters LPM. This is because the breakpoint is triggered by an instruction fetch, and the CPU fetches the next instruction while it executes the last. So the moment the breakpoint is triggered is the moment when the LPM bits are set. When an interrupt occurs, the already fetched NOP will be executed and then the ISR is entered. This kind of interleavce is neccessary to get the 'one cycle instructions' to work. Instructions altering the PC (MOV, JMP, CALL) have an additional cycle at the end which prevents the fetch, but in case of a simple bit setting inside the status register, this interleave is in effect.

    Neither NOP nor the LPM instructions are C commands. They need to be handled as assembly instructions and require special treatment (know-what-you-do) when using the debugger.

**Attention** This is a public forum