MSP430F249 USCI vs TIMER_A interrupts

Houston I have a problem.

Im working on a complex program, I have :

  • One rtc using TIMER_A and executing a list of functions every 1ms

  • Interrups on some IO

  • GPIO IIC …

  • USCI in uart mode running at 115200

Everything seems to works at 9600. But when it runs at 115200 I miss some bytes in reception …

When I desactivate my rtc and all the works linked with, UART reception works better.

My UART rx interrupt seems to have an highest priority than my TIMER_A so why it doesnt works ?

Best regard.

Ive rechecked interrupts priorities, and my older document is wrong, my TIMER_A priority is higher …

Priorities arent customizable son I dont know how to solve my problem …

If anybody have a solution …

Thanks.

Missing bytes in reception probably means that your machine is busy in an ISR or critical section for longer than it takes to receive one byte. I had a similar problem like this recently where the UART RX ISR took too long to figure out what thread was blocking on the RX queue and I missed characters. This problem also went away if I lowered the communication speed.

You need to profile your machine and figure out what part of the code it’s in when characters are being missed. Hook up one channel of a logic analyzer to your UART RX line, and another to a GPIO pin. Set the GPIO pin when you enter your UART RX ISR and reset it when you exit. Then look where the edges of the GPIO signal occur relative to the RX line. This way you’ll be able to tell if your machine is spending too much time in the ISR and is missing characters.

Of course, if you’re running a preemptive kernel, a higher priority interrupt may be taking control of execution, so you may need to use more than one GPIO for debugging.

Let me know if this helps,

Mateja

Not a lot of information to go on, but one solution may be to increase your processor clock speed. The MSP430x2xx family can go up to 16 MHz. If you are already running at the maximum, you will need to rework your code. Remember to keep interrupt service routines as short as possible; you may need to write them in assembler. Use a large enough buffer for the async so that you can process outside of the ISR without losing characters. Global variables may need to be used to facilitate information sharing.

Sounds like a challenging project. You need to think carefully about how the pieces fit together. A book you might want to check out is [“MSP430 State Machine Programming with the ES2274” by Tom Baugh. It covers using state machines to make code small and fast and is an excellent resource. Although he uses a different processor, the principles apply to all of the MSP430’s.](http://www.softbaugh.com/ProductPage.cfm?strPartNo=ISBN:978-0-9754759-2-8)

My MCU running at 8MHz, I will try 16MHz.

My MCU receives messages at 115200b, and my TIMER_A generates a tick every one ms to count time.

Some of my software modules can hook this tick to manage themselves. Obviously the modules do the less work in this hooked call. But maybe it can be optimised.

There is my rtc :

#pragma vector=TIMERA0_VECTOR
// Milisecond interrupt  
__interrupt void realtime_clock_ISR(void)   
{   
    // Parse works
    for (rtc_works_count_parse = 0; rtc_works_count_parse < rtc_works_count; rtc_works_count_parse++)
    {
    	if (rtc_works[rtc_works_count_parse] != 0) (*rtc_works[rtc_works_count_parse])();
    }
    
    TACCR0 += 1000;
}

void rtc_init(void)
{
	rtc_works_count = 0;
	
	TACTL &= ~(BIT4 | BIT5);	// Stop timer   
    
    TACTL |= TBSSEL_2;	// External clock, continuous
    TACTL |= ID_3;	// Divided by 8
	TACCR0 = 1000;	// 1 ms
	TACCTL0 |= CCIE;	// Enable interrupt   
	
	TACTL |= MC_2;  // Start timer  
}

void rtc_add_work(void (* work)(void))
{
	if (rtc_works_count < RTC_WORK_COUNT_CAPACITY)
	{
		rtc_works[rtc_works_count] = work;
		rtc_works_count ++;
	}
}

Looks like you are doing most of your processing within the interrupt (i.e. calling your functions). The way that this is normally done is that you set a flag to indicate the 1 millisecond event and then exit the ISR. In your main loop, you would check for the flag and if set, clear it and run your routines. The way it is now, once you are in your TimerA0 ISR, no other interrupts will get serviced until you exit the ISR and that is most likely the cause of your missed characters when running at 115.2K

HTH,

gm