cancel
Showing results for 
Search instead for 
Did you mean: 

UART0 and TIMER1 interrupts issue

lillian_200601
Associate II
Posted on November 13, 2009 at 07:22

UART0 and TIMER1 interrupts issue

9 REPLIES 9
lillian_200601
Associate II
Posted on May 17, 2011 at 09:57

Hi Lakata,

Thank you very much for your help. I searched this forum before I posted my message. I found their issues are a little different from mine. Their program will be crashed when two interrupts are running at same time. My prorgam can run properly, but accidentally receive wrong data.

I try your method and put dummy read in the beginning of ISR of UART. However, I still get wrong data sometimes. Any other suggestions? Thanks a lot!

Lillian

lillian_200601
Associate II
Posted on May 17, 2011 at 09:57

Hi,

I have questions regarding uart receive and timer OC interrupts. I am using STR912FAZ44H6 and keil uVision3.

1. IF I run the uart0 alone, the device can receive data correctly.

2. IF I run the timer alone, the device can get interrupt every 1 ms.

3. If I combine uart and timer together. Both work fine. However, the device receives wrong data every two or three minutes. For example, I should receive data ''ABCD'', but sometimes I will receive ''ABCCD'', or ''AABCD'', and so on.

My configuration is as follows:

UART_InitStructure.UART_WordLength = UART_WordLength_8D;

UART_InitStructure.UART_StopBits = UART_StopBits_1;

UART_InitStructure.UART_Parity = UART_Parity_No ;

UART_InitStructure.UART_BaudRate = 115200;

UART_InitStructure.UART_HardwareFlowControl = UART_HardwareFlowControl_None;

UART_InitStructure.UART_Mode = UART_Mode_Tx_Rx;

UART_InitStructure.UART_FIFO = UART_FIFO_Disable;

UART_DeInit(UART0);

UART_Init(UART0, &UART_InitStructure);

/* Enable the UART0 */

UART_Cmd(UART0, ENABLE);

UART_ITConfig(UART0, UART_IT_Receive, ENABLE);

VIC_DeInit();

VIC_Config(UART0_ITLine, VIC_IRQ, 2);

VIC_ITCmd(UART0_ITLine, ENABLE);

/* timer set up */

TIM_DeInit(TIM1); /* TIM1 Deinitialization */

/* TIM1 Structure Initialization */

TIM_StructInit(&TIM_InitStructure);

/* TIM1 Configuration in Output Compare Mode */

TIM_InitStructure.TIM_Mode = TIM_OCM_CHANNEL_1;

TIM_InitStructure.TIM_OC1_Modes = TIM_TIMING;

TIM_InitStructure.TIM_Clock_Source = TIM_CLK_APB;

TIM_InitStructure.TIM_Clock_Edge = TIM_CLK_EDGE_FALLING;

TIM_InitStructure.TIM_Prescaler = 0x64;

TIM_InitStructure.TIM_Pulse_Length_1 = 0x3BB;

TIM_Init (TIM1, &TIM_InitStructure);

/*Enable TIM1 Output Compare1 Interrupt */

TIM_ITConfig(TIM1, TIM_IT_OC1, ENABLE);

VIC_Config(TIM1_ITLine, VIC_IRQ, 3);

VIC_ITCmd(TIM1_ITLine, ENABLE);

TIM_CounterCmd(TIM1, TIM_START);

The interrupt routines:

void TIM1_IRQHandler(void)

{

TIM_ClearFlag(TIM1, TIM_FLAG_OC1);

TIM_CounterCmd(TIM1, TIM_CLEAR);

pid_count++;

VIC0 -> VAR = 0xFF;

VIC1 ->VAR = 0xFF;

}

void UART0_IRQHandler(void)

{

if(UART_GetITStatus(UART0, UART_IT_Receive)!= RESET)

{

if((UART_GetFlagStatus(UART0, UART_FLAG_RxFIFOEmpty) != SET)&&(RxCounter < RxBufferSize))

{

UART_RxBuffer[RxCounter] = UART0->DR;

if ( UART_RxBuffer[RxCounter] == 0x0D )

{

UART_RxBuffer[RxCounter] = 0x00; //save NULL to string instead of CR

FLAG.B.CR = 1; //If CR, set flag

}

if ( UART_RxBuffer[RxCounter] == 0x0A && FLAG.B.CR == 1 )

{

UART_RxBuffer[RxCounter] = 0x00; //save NULL to string instead of LF

FLAG.B.CR = 0; //If CR, set flag

FLAG.B.RS232 = 1; //If CR,LF set RS-232 input string ready flag

}

RxCounter++; //increment the RX buffer pointer

}//END OF UART_GETFLAG

}//END OF UART_GETITSTATUS

VIC0 ->VAR = 0xFF;

VIC1 ->VAR = 0xFF;

}

Anyone can point out what I am wrong in my program. Greatly appreciate any inputs.

mark9
Associate II
Posted on May 17, 2011 at 09:57

Search this discussion group for ''interrupts'' and you'll see a lot of discussion on this.

Basically, the problem comes down to the fact that the master IRQ should only read from VIC0->ADDR. Then your TIM and UART ISRs should do the following:

For TIM (which is VIC0),

isr {

// do something

VIC0->ADDR = 0;

}

For UART (which is VIC1),

isr {

x = VIC1->ADDR; // dummy read

// do something

VIC1->ADDR = 0;

}

The problem is that if write to both VIC0 and VIC1, you can mistakenly lose an interrupt if they happen at the same time.

mark9
Associate II
Posted on May 17, 2011 at 09:57

Here is my IRQ Handler:

IRQHandler

SUB lr,lr ,#4

SaveContext r0,r12

LDR r0, = VectorAddress

LDR r0, [r0] ; Read the routine address from VIC0 Vector Address register

BLX r0 ; Branch with link to the IRQ handler.

RestoreContext r0,r12

Here is my timer:

void BSP_TimerISR(void) {

uint16_t cmp_value;

cmp_value = TIM0->OC1R; // get the current compare value

TIM0->SR &= ~TIM_IT_OC1; // clear timer interrupt flag

cmp_value += timerTicksPerMillisecond; // Calculate a new ouput compare value

TIM0->OC1R = cmp_value; // Set the output compare register

jiffyStruct.u32++;

VIC0->VAR = 0x00000000; // Signal the end of the interrupt

}

My UART interrupt:

static void UART0_ISR(void) {

volatile uint32_t dummy = VIC1->VAR; // required to update the priority logic

UART0->ICR = UART_IT_Receive;

#define RXFE 0x0010 // rx FIFO 1/2 empty flag bit

#define TXFE 0x0080 // tx FIFO 1/2 empty flag bit

// serial->rxInterrupts++;

while (!(UART0->FR & RXFE) ) { // while not empty

uint16_t b = UART0->DR; // read UART buffer

if (b & 0xFF00) {

// serial->rxErrorCounter++;

} else {

// serial->rxBytes++;

}

if (hwMasterMode == READING) {

if (hwSerialRS485InBufferWritePtr

hwSerialRS485InBuffer[hwSerialRS485InBufferWritePtr] = b;

hwSerialRS485InBufferWritePtr++;

} else {

// overflow

}

} else {

hwSerialRS485OutputEchoCount--;

if (hwSerialRS485OutputEchoCount <=0) {

HW_SerialPort0ReadMode();

UART0->CR &= ~UART_CR_LBE; // disable loop-back, so we can read again

hwSerialRS485OutBufferWritePtr = hwSerialRS485OutBufferReadPtr = 0;

hwMasterMode = READING;

}

}

}

if (UART0->RIS & UART_IT_Transmit ) { // Transmit interrupt

// the tx buffer is guaranteed to be at least half empty, ie 8 bytes can be written,

// so let's write them.

#if HW_UART_BUFFER_LENGTH > 1

uint32_t i = 0;

while (hwSerialRS485OutBufferReadPtr < hwSerialRS485OutBufferWritePtr && i < (HW_UART_BUFFER_LENGTH/2) ) {

// transfer 1 byte to the tx buffer

UART0->DR = hwSerialRS485OutBuffer[hwSerialRS485OutBufferReadPtr++];

i++;

}

if (UART0->FR & TXFE) { // Transmit fifo totally empty

if ( hwSerialRS485OutBufferReadPtr != hwSerialRS485OutBufferWritePtr) {

// uhoh

i=i;

}

// we got to the end of the tx buffer, so now turn the RS488 bus to read mode

HW_SerialPort0ReadMode();

// reset the buffer points

hwSerialRS485OutBufferWritePtr = hwSerialRS485OutBufferReadPtr = 0;

}

#else

if (hwSerialRS485OutBufferReadPtr < hwSerialRS485OutBufferWritePtr ) {

// transfer 1 byte to the tx buffer

UART0->DR = hwSerialRS485OutBuffer[hwSerialRS485OutBufferReadPtr++];

}

#endif

UART0->ICR = UART_IT_Transmit ; // clear transmit interrupt

}

VIC1->VAR = 0x00000000; // required to update the priority logic

}

Also be sure to install a default ISR

static uint32_t bspVIC_ISR_Count = 0;

static void BSP_VIC_ISR(void) {

bspVIC_ISR_Count++;

}

...

VIC0->DVAR = (u32)BSP_VIC_ISR;

VIC1->DVAR = (u32)BSP_VIC_ISR;

lillian_200601
Associate II
Posted on May 17, 2011 at 09:57

Hi lakata,

Sorry for my late response since I am just back from vocation. Thank you very much for your source code. I compare yours with mines. The only differences are that you put clear pending bit ''UART0>ICR = UART_IT_RECEIVE'' inside of UART ISR and startup code --- IRQ handler.

My IRQ handler is as follows:

; Vectored Interrupt Controller (VIC) definitions

VectorAddr EQU 0xFFFFF030 ; VIC Vector Address Register

VectorAddrDaisy EQU 0xFC000030 ; Daisy VIC Vector Address Register

AREA IRQ, CODE, READONLY

ARM

PRESERVE8

ALIGN

EXPORT IRQHandler

IRQHandler

SUB LR, LR, #4 ; Update Link Register

STMFD SP!, {R0-R12, LR} ; Save Workspace & LR to Stack

MRS R0, SPSR ; Copy SPSR to R0

STMFD SP!, {R0, R1} ; Save SPSR to Stack (8-byte)

LDR R0, =VectorAddr

LDR R0, [R0] ; Read the Routine Address

LDR R1, =VectorAddrDaisy

LDR R1, [R1]

; Padding between the acknowledge and re-enable of interrupts

; For more details, please refer to the following URL

;

http://www.arm.com/support/faqip/3682.html

NOP

NOP

MSR CPSR_c, #0x1F ; Switch to SYS Mode and enable IRQ

STMFD SP!, {R0, LR} ; Save Link Register (8-byte Stack)

LDR LR, =IRQReturnAddress ; Read the Return Address

BX R0 ; Branch to the IRQ Handler

IRQReturnAddress

LDMFD SP!, {R0, LR} ; Restore Link Register (8-byte Stack)

MSR CPSR_c, #0xD2 ; Switch to IRQ Mode

LDR R0, =VectorAddr ; Write to the VectorAddress to clear

STR R0, [R0] ; the respective Interrupt

LDR R1, =VectorAddrDaisy ; Write to the VectorAddressDaisy to

STR R1, [R1] ; clear the respective Interrupt

LDMFD SP!, {R0, R1} ; Restore SPSR to R0

MSR SPSR_cxsf, R0 ; Restore SPSR

LDMFD SP!, {R0-R12, PC}^ ; Return to program

END

;*************************************************************************

In PC side, I program LABVIEW and send commands to my development device with STR912 continueously (Stress test). I find some puzzle things.

1. If there is no statement ''UART0>ICR = UART_IT_RECEIVE'' inside ISR of UART , my development device will receive wrong data around every one or two minutes.

2. If I put the statement ''UART0>ICR = UART_IT_RECEIVE'' in the end of UART ISR, my development device will stop receiving data after a few minutes. UART0 doesn't generate UART Receive Interrupt anymore since then.

I set the UART FIFOs disabled. Anybody can help me clarify whether I need to put ''UART0>ICR = UART_IT_RECEIVE'' inside of UART ISR. Anyway I still have issues about receiving wrong data sometimes. Thank you very much for your all other suggestions.

Lillian

kelhajjam9
Associate
Posted on May 17, 2011 at 09:57

Hi,

Please, I'm new to this,

where do I have to put the code for the irqhandler?

Quote:

IRQHandler

SUB lr,lr ,#4

SaveContext r0,r12

LDR r0, = VectorAddress

LDR r0, [r0] ; Read the routine address from VIC0 Vector Address register

BLX r0 ; Branch with link to the IRQ handler.

RestoreContext r0,r12

I have tried to put it in the startup but I think I didn't know how to do it, I found no documentation for that, please if you could help me.

I have an interrupt that stops at the level of the handler, I think I need to change my startup to make it resume from the main program.

thank you very much

anilkumarcr
Associate
Posted on May 17, 2011 at 09:57

Hi,

I got into a similar problem with the UART interface on 912 FW 44 controller. I am trying to use the UART0 at the baud rate of 115200. When the Transmit and Recieve FIFOs are disabled, intemittently, interrupts get missed (and I wont be able to read the byte). When I lowered the baud rate to 57600, the interrupts were perfect and I was able to read all the bytes. Unfortunately, my requirement states, I need to run it at 115200:-(

Also, with the FIFOs enabled it works well for both 115200 and 57600 bauds.Following are my questions.

1. Is there is a known limitation for the UARTs on this controller, when used with out the FIFOs at 115200 baud rate?

2. If there is no limitations, can you provide me any hints about anything I might be doing wrong? The only other interrupt that is enabled is the Timer0 interrupt.

After reading the message from LILLIAN, I guess I will disable the TIMER and see if I can read all the data from the UART.

If anyone had the similar issue and had a solution please post it to me

Thank You,

Anil

nle
Associate II
Posted on May 17, 2011 at 09:57

Quote:

On 06-01-2009 at 15:43, Anonymous wrote:

Hi lakata,

....

In PC side, I program LABVIEW and send commands to my development device with STR912 continueously (Stress test). I find some puzzle things.

1. If there is no statement ''UART0>ICR = UART_IT_RECEIVE'' inside ISR of UART , my development device will receive wrong data around every one or two minutes.

2. If I put the statement ''UART0>ICR = UART_IT_RECEIVE'' in the end of UART ISR, my development device will stop receiving data after a few minutes. UART0 doesn't generate UART Receive Interrupt anymore since then.

I set the UART FIFOs disabled. Anybody can help me clarify whether I need to put ''UART0>ICR = UART_IT_RECEIVE'' inside of UART ISR. Anyway I still have issues about receiving wrong data sometimes. Thank you very much for your all other suggestions.

Lillian

Greetings.

We are having similar problems with uart: missing characters and uart interrupt stops triggering after some time. Using STR912FAW44. At other tests with minor modifications, it seems to work properly more often like 70%, but the remaining 30% still have the same problems.

We have just inherited this project, and the source code is a mess, and we are new to ARM and still learning with difficulty.

We are using an RTOS, but we believe it is not the cause of our problems.

We are now investigating STR912 interrupt management issues that may be the cause, based on STMicro errata on the cpu revision that we are using.

I have noticed your code as similar to ours, except that currently it has been modified for some reason in this line:

original:

MSR cpsr_c,#0x1F

current:

MSR cpsr_c,#0x1F | I_Bit

Why I_Bit is set we have not yet received information from the original team. This will disable the interrupts.

Other info:

We are having problems with Uart1. Uart0 is also used but does not seem to have any problems. We have also utilized Uart2 for temporary debug output. Originally Uart1 enabled the FIFO. But someone from old team modified the settings to not use FIFO, without updating the Uart1 handler. We are fixing this now. But this would probably not cause the other problem of interrupts getting blocked.

THank you for any info.

nle
Associate II
Posted on May 17, 2011 at 09:57

i updated information on related topic ''Daisy chained interrupt errata fix''