vespaman2 wrote on Monday, September 03, 2012:
I have a set-up where two threads are sending on the same UART port in about the same time. The port is protected by a mutex which is released when a tx has ended.
The problem is that the thread with the lowest priority always ends up in the vListInsert() loop when looking in its message box.
This does not seem to happen if the threads has the same priority. (Or at least, I have not seen it).
At first, I thought it was interrupt stack related, but I have now dismissed that, since it is over hundred bytes unused in each thread stack.
Then I thought it was related to the portEND_SWITCHING_ISR(), which I found a bug in. (see my previous forum thread containing info about interrupt priorities and levels: https://sourceforge.net/projects/freertos/forums/forum/382005/topic/5563352 )
Then I thought the mutex protection did not work as it should, but now I have done many tests on that, so I pretty confident it works.
So now I’m leaning towards something is wrong with my port (very similar to the reference Coldfire 52259 demo). Maybe a set-up thingy or a misunderstanding on my side.
I have tried to disable configUSE_PREEMPTION, but issue remains.
I have tried to disable configUSE_RECURSIVE_MUTEXES, but issue remains.
How can I boil it down further?
Code fragments:
void uart_send( int uartch, unsigned char *tx_buff, unsigned short len )
{
if( xSemaphoreTake( uart_dev[uartch].mutex, 5000 ))
{
vTaskDelay(40);
uart_dev[uartch].tx_buff = tx_buff;
uart_dev[uartch].len = len;
MCF_UART_UCR(uartch) = MCF_UART_UCR_TX_ENABLED;
}
else
{
DEBUG("uart_send: Fail, could not aquire mutex!");
}
}
// Note: The delay above triggers the problem almost instantly,
// without it, days can pass without bug appearing.
// Uart 0 @ interrupt source 13
void __attribute__ ((interrupt)) __cs3_isr_interrupt_77( void )
{
unsigned char usr = MCF_UART0_USR;
unsigned char uisr = MCF_UART0_UISR;
int task_woken = FALSE;
if( usr & MCF_UART_USR_RXRDY ) // rx interrupt ..
{
[..]
}
if( usr & MCF_UART_USR_TXRDY && uart_dev[0].dma == FALSE ) // tx interrupt
{
if( 0 <= --uart_dev[0].len )
MCF_UART0_UTB = *uart_dev[0].tx_buff++;
else
{
MCF_UART0_UCR = MCF_UART_UCR_TX_DISABLED;
xSemaphoreGiveFromISR(uart_dev[0].mutex, &task_woken );
}
}
portEND_SWITCHING_ISR( task_woken );
}
FreeRTOSConfig.h:
#define configUSE_PREEMPTION 1
#define configUSE_IDLE_HOOK 0
#define configUSE_TICK_HOOK 0
#define configCPU_CLOCK_HZ ( ( unsigned portLONG ) 64000000 )
#define configTICK_RATE_HZ ( ( portTickType ) 1000 )
#define configMINIMAL_STACK_SIZE ( ( unsigned portSHORT ) 200 )
#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 15 * 1024))
#define configMAX_TASK_NAME_LEN ( 5 )
#define configUSE_TRACE_FACILITY 1
#define configGENERATE_RUN_TIME_STATS 1
#define configUSE_16_BIT_TICKS 0
#define configIDLE_SHOULD_YIELD 0
#define configUSE_CO_ROUTINES 0
#define configUSE_MUTEXES 1
#define configCHECK_FOR_STACK_OVERFLOW 2
#define configUSE_RECURSIVE_MUTEXES 1
#define configQUEUE_REGISTRY_SIZE 0
#define configUSE_COUNTING_SEMAPHORES 0
#define configMAX_PRIORITIES ( ( unsigned portBASE_TYPE ) 5 )
#define configMAX_CO_ROUTINE_PRIORITIES ( 2 )
/* Set the following definitions to 1 to include the API function, or zero
to exclude the API function. */
#define INCLUDE_vTaskPrioritySet 0
#define INCLUDE_uxTaskPriorityGet 0
#define INCLUDE_vTaskDelete 1
#define INCLUDE_vTaskCleanUpResources 0
#define INCLUDE_vTaskSuspend 0
#define INCLUDE_vTaskDelayUntil 1
#define INCLUDE_vTaskDelay 1
#define INCLUDE_uxTaskGetStackHighWaterMark 1
#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() hr_timer_init()
#define portGET_RUN_TIME_COUNTER_VALUE() hr_timer_get_value()
#define configYIELD_INTERRUPT_VECTOR 16UL
#define configKERNEL_INTERRUPT_PRIORITY 1
#define configMAX_SYSCALL_INTERRUPT_PRIORITY 7