Still locking after portEND_SWITCHING_ISR

anonymous wrote on Tuesday, March 13, 2012:

Yesterday I asked a question about eternal lock after context switch (here
But unfortunately, even right procedure of serving interrupt still causes eternal lock!

It looks like this:

static portBASE_TYPE xHigherPriorityTaskWoken;
	irq++; //for debug purposes
		__asm("NOP"); //here I can place a break, after that all tasks remain blocked forever
	xSemaphoreGiveFromISR(IRQSemph, &xHigherPriorityTaskWoken);

There are two tasks, one for actual serving this interrupt, high-priority, which starts with xSemaphoreTake(IRQSemph, portMAX_DELAY);
and another, with lower priority, which is blocked, waiting signal form high-priority task.

I suppose, that when breakpoint is reached (irq count == 2), ISR interrupts this high priority task, while it is processing last ISR (irq == 1). But I don’t understand, why this is causing this lock!

When I am entering xSemaphoreGiveFromISR, I can see that it’s pxQueue->xTxLock is 0, so no actions with even list is taken, just data copy, inctement of xTxLock and return of  FALSE;

Also pxQueue->xTasksWaitingToReceive->uxNumberOfItems = 2.

What does this mean, why there is two tasks, waiting for receive? The only one task, that uses this semaphore is my high-priority routine…

rtel wrote on Tuesday, March 13, 2012:

I’m not sure I understand your problem, but could the issue be in your task implementation?  Are you doing something like leaving the scheduler locked, or calling API functions with the scheduler locked?


anonymous wrote on Tuesday, March 13, 2012:

This is just a driver for radio tranciever.
Here is my high-priority task:

static void taskDriverIRQHandler(void *pvParameters)
u8 Status;
xSemaphoreTake(IRQSemph, portMAX_DELAY);
xSemaphoreTake(SPI_DMA_Tx, portMAX_DELAY);

I want it work in such way:
transmitter task (low priority) blocks on TxFIFOFree. Radio module asserts it’s irq pin, causing external interrupt - it’s isr is in my first post. ISR gives IRQSemph, also clearing EXIT bit.
taskDriverIRQHandler task unblocks, waits for all DMA transfers to be complete (actualy, they are all complete much earlier, I checked that), then sends to transiever SPI command to clear it’s internal interrupt status - without that there will be no more interrupts, as EXTI handles high-to-low transition, and IRQ pin remains constant low.
Then taskDriverIRQHandler should give one more slot in TxFIFOFree, unblocking Tx task again.
But it doesn’t work in that way!

What I know, is that Tx task finishes it’s DMA transfers and blocks waiting TxFIFOFree. After some time, data is being sent by module and it asserts IRQ pin. ISR serves it, unblocks taskDriverIRQHandler, wich defenitly resets module’s IRQ status.
Than some black magic happens, which I can not understand or even debug (because braking or even adding some tracing causes functions to execute slower and second interrupts does not ruin everything).
All I know is that second interrupt arrives, my system enters ISR, but tracing internals of xSemaphoreGive call, shows that IRQSemph is considered to be locked, it’s pxQueue->xTxLock is 0, not queueUNLOCKED.
So, semaphore does not unblock it, just increment lock counter - but there is no other tasks running to unblock it either.

anonymous wrote on Tuesday, March 13, 2012:

I just found this damned bug.
Sorry for my questions, it is really stupid mistake.
Obviously, I shouldn’t use NVIC-configuration routines like this:

NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel5_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = configLIBRARY_KERNEL_INTERRUPT_PRIORITY-3;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init( &NVIC_InitStructure );
	 NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn;
	 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = configLIBRARY_KERNEL_INTERRUPT_PRIORITY-2;
	 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
	 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

I wanted to set priorities to
but I think i missed somethin in documentation on theese functions, so both priorities were set to 0! Highest possible priority, yeah.

When I checked it and replaced theese calls with conventional CMSIS


all began to work.

Still really  appreciate your help, big thanks!

anonymous wrote on Tuesday, March 13, 2012:


This is the line I missed, btw)