Hello All,
I am working on the BSL project which was working fine until I went ahead to implement LPM0 and enabled receiving UART Chars through ISR instead of reading the RX buffer when RXIFG is set.
My project uses UCA0 for UART and WDT Timer Interval for time outs. When it was working, there were no interrupt routines enabled and would look for IFG2 & UCA0RXIFG to receive from UCA0RXBUF directly. I implemented LPM0 and it changed the receive mechanism and now I receive in the __interrupt void usart0_rx(void) after enabling IE2 |= UCA0RXIE; It would help me wake-up from the LPM0 as it generates an interrupt. In my initialization sequence I disable watchdog timer interrupt using IE1 &= ~WDTIE; and then clear the watchdog interval timer flag.
My UART receive seems to be working fine when I send .txt file and not use timeout while receiving characters. However, when I transfer my firmware through Xmodem the program breaks at the very first byte i think and goes to _c_int00_noargs_noexit().
__interrupt void usart0_rx(void) puts received characters in my rx_buf ring buffer and i use following functions to read characters from the ring buffer. One of GetCharTmo() uses time out.
extern "C"
__interrupt void usart0_rx(void)
{
char ch;
ch = UCA0RXBUF; // get the character we have read
if(!rx_buf.put(ch))
{
}
else
{
}
__bic_SR_register_on_exit(LPM0_bits);
}
int main(int argc, char* argv[])
{
....
// Serial port initialization
UCA0CTL1 = UCSSEL1 + UCSWRST; // **Initialize USCI state machine**
IE2 &= ~UCA0RXIE; // Disable USCI_A0 RX interrupt
UCA0BR0 = 0x15; //0xAD; //0x11; // 16mhz/57600 = //10mhz/9600 = 1041.667 = 0x0411 -> divisor for 9600 baud
UCA0BR1 = 0x01; //0x00; //0x04; // 277.78 = 0x115 //10mhz/57600 = 173.111 = 0x00AD -> divisor for 57600 baud
UCA0MCTL = UCBRS2 + UCBRS0; //Modulation UCBRSx = 5 rounding error
UCA0CTL1 &= ~UCSWRST; //**Initialize USCI state machine**
P3SEL |= BIT4 + BIT5; // P3.4,5 = USCI_A0 TXD/RXD
P3SEL |= BIT0;
P3DIR &= ~BIT0;
// Watchdog timer initialization - we put the watchdog timer into interval mode
// Change WDT+ to interval timer mode, ACLK, clock/8192 interval
IE1 &= ~WDTIE; // disable the watchdog timer interupt - we don't use
IFG1 &= ~WDTIFG; // clear the watchdog interval timer flag
WDTCTL = WDTPW + WDTCNTCL + WDTTMSEL + WDTIS0; // Change WDT+ to interval timer mode
// initialize variables
//P3OUT |= 0x08;
IE2 |= UCA0RXIE; // Enable USCI_A0 RX interrupt
__bis_SR_register(GIE); //Enable the global interrupts, currently the rx interrupts from the Mac and hso
...
while(1)
{
__bis_SR_register(LPM0_bits+GIE);
...
/* reading from ring buffer to char cmd[256] here */
ProcessCommand(cmd); // pass the command to the command processor
}
}
void TimerSpin()
{
static int TIMER_TICK_COUNT = 2;
static int secCounter = TIMER_TICK_COUNT;
if( (IFG1 & WDTIFG) && --secCounter )
{
secCounter = TIMER_TICK_COUNT;
IFG1 &= ~WDTIFG;
// count down any times that are active
if( getCharTimer != 0 ) getCharTimer--;
}
return;
}
int16_t GetChar()
{
char ch;
while (!rx_buf.get(ch))
{
TimerSpin();
}
return ch;
}
int16_t GetCharTmo(uint16_t tmo)
{
char ch;
getCharTimer = tmo;
while (!rx_buf.get(ch))
{
TimerSpin();
if( getCharTimer == 0 )
return -1;
}
return ch;
}
Note: When in LPM0 my program waits to receive a character. As soon as it receives a character it wakes up from the low power mode and disables LPM0 in receive Interrupt routine and then waits for firmware in normal mode.
Pausing the debug mode gives me below stack.
I do not know what is happening that causes my program to break. Can not print anything on the terminal when i start receiving through Xmodem. Breaks when I start sending the firmware image. I think has to do with interrupt. Any debugging help would be appreciated.