bones23 wrote on Saturday, January 19, 2008:
I am working on an str91x board and am having problems with my uart interrupts. The interrupt does not fire until the second character has been received from input. Essentially this causes the last character of any message sent to the device to sit ignored in the Rx FIFO until the next message is sent. Has anybody had this problem? If so how did you fix it? My code is below.
//serial set up function
xComPortHandle xSerialPortInitMedium( unsigned portLONG ulWantedBaud, unsigned portBASE_TYPE uxQueueLength, int comNum )
{
xComPortHandle xReturn;
UART_InitTypeDef xUARTx_Init;
GPIO_InitTypeDef GPIO_InitStructure;
xSemaphoreHandle semiphorTest;
xQueueHandle xRxedChartest;
UART_TypeDef* UARTx;
switch(comNum){
case 0:
UARTx = UART0;
break;
case 1:
UARTx = UART1;
break;
case 2:
UARTx = UART2;
break;
}
switch(comNum){
case 0:
xReturn = &COM0;
break;
case 1:
xReturn = &COM1;
break;
case 2:
xReturn = &COM2;
break;
}
switch(comNum){
case 0:
xRxedChars0 = xQueueCreate( uxQueueLength, ( unsigned portBASE_TYPE ) sizeof( signed portCHAR ) );
xRxedChartest = xRxedChars0;
vSemaphoreCreateBinary( xTxFIFOSemaphore0 );
semiphorTest = xTxFIFOSemaphore0;
break;
case 1:
xRxedChars = xQueueCreate( uxQueueLength, ( unsigned portBASE_TYPE ) sizeof( signed portCHAR ) );
xRxedChartest = xRxedChars;
vSemaphoreCreateBinary( xTxFIFOSemaphore );
semiphorTest = xTxFIFOSemaphore;
break;
case 2:
xRxedChars2 = xQueueCreate( uxQueueLength, ( unsigned portBASE_TYPE ) sizeof( signed portCHAR ) );
xRxedChartest = xRxedChars2;
vSemaphoreCreateBinary( xTxFIFOSemaphore2 );
semiphorTest = xTxFIFOSemaphore2;
break;
}
/* If the queue/semaphore was created correctly then setup the serial port
hardware. */
if( ( xRxedChartest != serINVALID_QUEUE ) && ( semiphorTest != serINVALID_QUEUE ) )
{
/* Pre take the semaphore so a task will block if it tries to access
it. */
switch(comNum){
case 0:
xSemaphoreTake( xTxFIFOSemaphore0, 0 );
break;
case 1:
xSemaphoreTake( xTxFIFOSemaphore, 0 );
break;
case 2:
xSemaphoreTake( xTxFIFOSemaphore2, 0 );
break;
}
/* Configure the UART. */
xUARTx_Init.UART_WordLength = UART_WordLength_8D;
xUARTx_Init.UART_StopBits = UART_StopBits_1;
xUARTx_Init.UART_Parity = UART_Parity_No;
xUARTx_Init.UART_BaudRate = ulWantedBaud;
xUARTx_Init.UART_HardwareFlowControl = UART_HardwareFlowControl_None;
xUARTx_Init.UART_Mode = UART_Mode_Tx_Rx;
xUARTx_Init.UART_FIFO = UART_FIFO_Enable;
/* Enable the UARTx Clock */
switch(comNum){
case 0:
SCU_APBPeriphClockConfig( __UART0, ENABLE );
break;
case 1:
SCU_APBPeriphClockConfig( __UART1, ENABLE );
break;
case 2:
SCU_APBPeriphClockConfig( __UART2, ENABLE );
break;
}
portENTER_CRITICAL();
{
/* Configure the UART itself. */
switch(comNum){
case 0:
UART_DeInit( UART0 );
UART_Init( UART0, &xUARTx_Init );
UART_ITConfig( UART0, UART_IT_Receive | UART_IT_Transmit, ENABLE );
UART0->ICR = serCLEAR_ALL_INTERRUPTS;
UART_LoopBackConfig( UART0, DISABLE );
UART_IrDACmd( IrDA0, DISABLE );
VIC_Config( UART0_ITLine, VIC_IRQ, 7 );
VIC_ITCmd( UART0_ITLine, ENABLE );
UART_Cmd( UART0, ENABLE );
break;
case 1:
UART_DeInit( UART1 );
UART_Init( UART1, &xUARTx_Init );
UART_ITConfig( UART1, UART_IT_Receive | UART_IT_Transmit, ENABLE );
UART1->ICR = serCLEAR_ALL_INTERRUPTS;
UART_LoopBackConfig( UART1, DISABLE );
UART_IrDACmd( IrDA1, DISABLE );
VIC_Config( UART1_ITLine, VIC_IRQ, 8 );
VIC_ITCmd( UART1_ITLine, ENABLE );
UART_Cmd( UART1, ENABLE );
break;
case 2:
UART_DeInit( UART2 );
UART_Init( UART2, &xUARTx_Init );
UART_ITConfig( UART2, UART_IT_Receive | UART_IT_Transmit, ENABLE );
UART2->ICR = serCLEAR_ALL_INTERRUPTS;
UART_LoopBackConfig( UART2, DISABLE );
UART_IrDACmd( IrDA2, DISABLE );
VIC_Config( UART2_ITLine, VIC_IRQ, 10 );
VIC_ITCmd( UART2_ITLine, ENABLE );
UART_Cmd( UART2, ENABLE );
break;
}
lTaskWaiting = pdFALSE;
}
portEXIT_CRITICAL();
}
else
{
xReturn = ( xComPortHandle ) 0;
}
/* This demo file only supports a single port but we have to return
something to comply with the standard demo header file. */
return xReturn;
}
// IRQ handler
void UART0_IRQHandler( void )
{
signed portCHAR cChar;
portBASE_TYPE xTaskWokenByTx = pdFALSE, xTaskWokenByPost = pdFALSE;
while( UART0->RIS & mainRXRIS )
{
/*The interrupt was caused by a character being received. Grab the
character from the DR and place it in the queue of received
characters.*/
cChar = UART0->DR;
xTaskWokenByPost = xQueueSendFromISR( xRxedChars0, &cChar, xTaskWokenByPost );
}
if( UART0->RIS & mainTXRIS )
{
if( lTaskWaiting == pdTRUE )
{
/* This interrupt was caused by space becoming available on the Tx
FIFO, wake any task that is waiting to post (if any). */
xTaskWokenByTx = xSemaphoreGiveFromISR( xTxFIFOSemaphore0, xTaskWokenByTx );
lTaskWaiting = pdFALSE;
}
UART0->ICR = mainTXRIS;
}
/* If a task was woken by either a character being received or a character
being transmitted then we may need to switch to another task. */
portEND_SWITCHING_ISR( ( xTaskWokenByPost || xTaskWokenByTx ) );
}