cancel
Showing results for 
Search instead for 
Did you mean: 

Why can't I read from USARTx->SR in interrupt mode (STM32-Discovery)?

ptumati
Associate II
Posted on July 12, 2012 at 16:08

Hi,

Hardware -> STM32-Discovery IDE-> Keil uVision getBit(USART2->SR, position) works in the non-interrupt mode, but, it doesn't in the USARTn interrupt mode...! I have linked the USART1's TX to the USART2's RX. Usart1's TX is working correctly; I have checked it with a logic analyzer. Now, in both usarts, I notice that I can't read the value of USARTx->SR in the interrupt mode. The debugger in the uVision shows me the right values in the SR register; I see ORE, IDLE, RXNE, TC & TXE turned on. However, when I tried to retrieve the value of USARTn->SR, I get a 0. int b=USART1->SR; // returns 0 int b=USART_GetFlagStatus(USART2, USART_FLAG_RXNE); // returns 0 See the line against the comment [ISSUE] below... None of the code examples (receiveData within interrupt mode) that I have seen in this forum work. Is there something that I am missing? Whats going on here? Any suggestion/advice is highly appreciated. Thanks.

#include ''wrapper.h''
USART_InitTypeDef USART_InitTypeDef2={
9600,
USART_WordLength_8b,
USART_StopBits_1,
USART_Parity_No,
(USART_Mode_Rx | USART_Mode_Tx ),
USART_HardwareFlowControl_None
};
volatile
int
x=0;
unsigned 
char
buffer2[MAX_BUFFER_SIZE];
void
__setup_USART2_pins(
void
)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
void
__setup_USART2_Interrupt(
void
)
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0); 
// Enable the USARTx Interrupt 
NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
NVIC->ISER[1] |= (1 << (USART2_IRQn & 0x1F)); 
// enable interrupt in NVIC
}
void
initUSART2()
{
AFIO->MAPR &= ~(1 << 3); 
// clear USART2 remap
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOA , ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
__setup_USART2_pins();
__setup_USART2_Interrupt();
USART_Init(USART2,&USART_InitTypeDef2);
USART2->CR1 |= CR1_UE_Set; 
// Enable USART
USART2->CR1 |= USART_Mode_Tx; 
// Enable TX operation
USART2->CR1 |= USART_Mode_Rx; 
// Enable RX operation
USART2->CR1 |= USART_FLAG_RXNE ; 
// Enable RX interrupt mode
}
void
sendUSART2(
int
size)
{
int
index=0;
if
(buffer2==NULL)
return
;
// Iterate over the buffer2 and print char by char
for
(index = 0; index<size; index ++) {
USART_SendData(USART2, (uint8_t) buffer2[index]); 
// Wait until the TXE bit is set to 1
while
(!getBit(USART2->SR, 7));
if
(index>MAX_BUFFER_SIZE)
break
;
}
//Loop until the end of transmission; this is very important
while
(USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET);
}
void
USART2_IRQHandler()
{
volatile
int
b = USART_GetFlagStatus(USART2, USART_FLAG_RXNE); 
// <- [ISSUE]
buffer2[x++]=USART_ReceiveData(USART2);
return
;
}

4 REPLIES 4
Posted on July 12, 2012 at 17:33

Don't use BB access on the USART, it's pointless.

Don't write to the DR unless the TXE is actually set. Check it BEFORE not after. Don't read the DR unless the RXNE is actually set, it clears status. Decide if you want to use the library, or bit-bang the registers, it makes the code nightmarishly messy and hard to read/debug.


Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
ptumati
Associate II
Posted on July 13, 2012 at 02:29

Ok, removed all the BBs and cleaned up the code...   #include ''wrapper.h''

USART_InitTypeDef USART_InitTypeDef2={

9600,

USART_WordLength_8b,

USART_StopBits_1,

USART_Parity_No,

(USART_Mode_Rx | USART_Mode_Tx ),

USART_HardwareFlowControl_None

};

volatile

int

x=0;

unsigned

char

buffer2[MAX_BUFFER_SIZE];

void

__setup_USART2_pins(

void

)

{

GPIO_InitTypeDef GPIO_InitStructure;

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;

GPIO_Init(GPIOA, &GPIO_InitStructure);

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;

GPIO_Init(GPIOA, &GPIO_InitStructure);

}

void

__setup_USART2_Interrupt(

void

)

{

NVIC_InitTypeDef NVIC_InitStructure;

// Enable the USARTx Interrupt

NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

NVIC_Init(&NVIC_InitStructure);

}

void

initUSART2()

{

RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOA , ENABLE);

RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);

__setup_USART2_pins();

__setup_USART2_Interrupt();

USART_Init(USART2,&USART_InitTypeDef2);

USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);

USART_Cmd(USART2, ENABLE);

}

void

sendUSART2(

int

size)

{

int

index=0;

if

(buffer2==NULL)

return

;

// Iterate over the buffer2 and print char by char

for

(index = 0; index<size; index ++) {

// Wait until the TXE bit is set to 1

while

(!USART_GetFlagStatus(USART2, USART_FLAG_TXE));

USART_SendData(USART2, (uint8_t) buffer2[index]);

if

(index>MAX_BUFFER_SIZE)

break

;

}

//Loop until the end of transmission; this is very important

while

(USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET);

}

void

USART2_IRQHandler()

{

if

(USART_GetFlagStatus(USART2, USART_FLAG_RXNE)) // <-- [ISSUE]

buffer2[x++]=USART_ReceiveData(USART2);

return

;

}

 Thebehavioris the same, when the instruction counter is on line [ISSUE], I see the RXNE, ORE, IDLE, TC, TXE flags set in the debugger window (Keil uVision). Based on what I understand ''USART_GetFlagStatus'' should return a '1'. However, it returns a 0 whenever I press a F10 (next statement) and the counter never gets into the ''buffer2[x++]=USART_ReceiveData(USART2);'' statement.  Now, if I say ''a=USART2->SR'', it is still returning a '0'. This is strange to me.  

Posted on July 13, 2012 at 02:55

Nothing is looking egregious.

You're using the STM32 VL-Discovery? You're running in the hardware, not simulating?

You've selected the right part the STM32F100, and you're clocking via the PLL at only 24 MHz?

You're using the VLDiscovery firmware library, not the STM3210x v3.5.0?

You might want to keep x within the bounds of the buffer, and be aware that single stepping might not show every instruction, or exactly the code order if optimized. You might want to step at the assembler instruction level, not the C line level.
Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
ptumati
Associate II
Posted on July 13, 2012 at 03:00

Never mind, this looks like a bug in the Keil debugger. When I do a step-by-step debug, the debugger first reads the USART2->SR; this clears all the required flags; and when we go to the next step, the reset SR register is getting copied into the appropriate variable. However, when I don't monitor SR and don't put a break point on the [ISSUE] line, everything seems to work correctly.
Thanks for advising not to use the BB style of programming...