DMA usart issue on STM32F4

pierreculot wrote on Thursday, July 10, 2014:

Hello,
I’m working on STM32F437 and FreeRTOS 8.0.0.

I have a problem with USART and DMA transmit:
If I pass through InitVariablesForOs(), my DMA for USART transmit complete doens’t work. The first “111” is sent but the counter of the DMA is not decremented and obviously no DMA interrupt transmit complete(needed for RS485 direction)triggers. And in consequence the program wait endless the DMA buffer is empty before sendign the second “222”.

int main void (void)
{
InitVariablesForOs();//init mutex, queue and semaphore
Initlowlevel();//init hardware and NVIC
SendOnUsart1(“111”,3);
SendOnUsart1(“222”,3);
SendOnUsart1(“333”,3);
Initsometask here…
vTaskStartScheduler();

}

If I comment the first line DMA works well (obviously assert from Feertos will block later because the variable are NULL)

I think interrupt are correct:

void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;

/* Configure the NVIC Preemption Priority Bits */
NVIC_PriorityGroupConfig( NVIC_PriorityGroup_4 );

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 15;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

/* Enable the Ethernet global Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = ETH_IRQn;
NVIC_Init(&NVIC_InitStructure);

NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn;
NVIC_Init(&NVIC_InitStructure);

NVIC_InitStructure.NVIC_IRQChannel = SDIO_IRQn;
NVIC_Init(&NVIC_InitStructure);

NVIC_InitStructure.NVIC_IRQChannel = DMA2_Stream3_IRQn;
NVIC_Init(&NVIC_InitStructure);

/* Enable the USARTx Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_Init(&NVIC_InitStructure);

NVIC_InitStructure.NVIC_IRQChannel = DMA2_Stream7_IRQn;
NVIC_Init(&NVIC_InitStructure);

}

To be honnest I don’t see the link between os variable initialization and DMA. I ran step-by-step and I didn’t see why the behaviour is modified?
Because I can work without usart DMA, I disabled it.

Pierre

rtel wrote on Thursday, July 10, 2014:

Your interrupt code looks ok - and I agree that there is no obvious reason for a link between calling the function the operation of the DMA.

Please post the code InitVariablesForOs() so I can be sure.

Regards,
Richard Barry

pierreculot wrote on Friday, July 11, 2014:

Hi this is the code.
With only one of these lines appears the problem.

void InitVariablesForOs (void)
{
	os.xQueueHandle_RXFromBrowser = xQueueCreate(10, sizeof (messageFromBrowser_t));
	os.xQueueHandle_RXFromCodine = xQueueCreate(10, sizeof (messageStatusFromcodine_t));
os.signalACKfromCodineCard <span style="color: #333333">=</span> xQueueCreate(<span style="color: #0000DD; font-weight: bold">1</span>, <span style="color: #008800; font-weight: bold">sizeof</span> (commandeAcknowledge_t));

os.xQueueHandle_RXCodineStillAlive <span style="color: #333333">=</span> xQueueCreate(<span style="color: #0000DD; font-weight: bold">5</span>,<span style="color: #008800; font-weight: bold">sizeof</span>(U16));
os.SoftwareTimerCodineStillAlive <span style="color: #333333">=</span> xTimerCreate( (<span style="color: #008800; font-weight: bold">const</span> <span style="color: #333399; font-weight: bold">char</span> <span style="color: #333333">*</span>) <span style="background-color: #fff0f0">&quot;PollingCodine&quot;</span>, VAL_TIMER_CALL,
  						pdTRUE,	( <span style="color: #333399; font-weight: bold">void</span> <span style="color: #333333">*</span> ) <span style="color: #0000DD; font-weight: bold">0</span>, TimerCallback);

<span style="color: #888888">/*</span>

* Les mutex sont en variables static dans les fichiers
*/
InitMutex__cust_log_RAM_access();
InitMutex__List();
InitMutex__cust_log_SD_access();
InitMutex__cust_log_SD_access_technical();
InitMutex__GlobalRAM();
InitMutex__MuseogGlobalRAM();
InitMutex__Tablelogin();
InitSemaphore__DigOutput();
InitMutex__EEPROM_access();

<span style="color: #888888">/*LOG*/</span>
os.xQueue_log.xQueueFromModule <span style="color: #333333">=</span> xQueueCreate(<span style="color: #0000DD; font-weight: bold">1</span>, <span style="color: #008800; font-weight: bold">sizeof</span> (logFromModule_t));
os.xQueue_log.xQueueFromModuleMuseoguard <span style="color: #333333">=</span> xQueueCreate(<span style="color: #0000DD; font-weight: bold">1</span>, <span style="color: #008800; font-weight: bold">sizeof</span> (logFromModuleMuseoguard_t));
os.xQueue_log.xQueueFromWeb <span style="color: #333333">=</span> xQueueCreate(<span style="color: #0000DD; font-weight: bold">5</span>, <span style="color: #008800; font-weight: bold">sizeof</span> (logFromWeb_t));
os.xQueue_log.xQueueListenBroadcastServer <span style="color: #333333">=</span> xQueueCreate(<span style="color: #0000DD; font-weight: bold">2</span>, <span style="color: #008800; font-weight: bold">sizeof</span> (logFromModuleBroadcastMessage_t));
os.xQueue_log.xQueueTechnicalForDebug <span style="color: #333333">=</span> xQueueCreate(<span style="color: #0000DD; font-weight: bold">5</span>, <span style="color: #008800; font-weight: bold">sizeof</span> (logTechnicalDebug_t));

<span style="color: #888888">/*debug queues*/</span>

// vQueueAddToRegistry( os.xQueueListenBroadcastServer, (signed char*)“misc Queue” );
// vQueueAddToRegistry( os.xQueueHandle_RXFromBrowser, (signed char*)“misc Queue” );
// vQueueAddToRegistry( os.xQueueHandle_RXFromCodine, (signed char*)“misc Queue” );
// vQueueAddToRegistry( os.signalACKfromCodineCard, (signed char*)“misc Queue” );
// vQueueAddToRegistry( os.xQueueHandle_MessageMuseoguard, (signed char*)“misc Queue” );
// vQueueAddToRegistry( os.xQueueHandle_RXCodineStillAlive, (signed char*)“misc Queue” );
}

rtel wrote on Friday, July 11, 2014:

With only one of these lines appears the problem.

Do you mean that including any of these lines will cause the problem, or that including one specific line will cause the problem (if so, which one?).

If including any of these lines causes the problem then it would seem unlikely but not impossible it was the line itself that was the problem. I say not impossible because the lines are calling into the FreeRTOS kernel, which means critical sections will be being entered and exited - but that should definitely not cause a problem.

Are you 100% sure the start up code is initialising the system correctly? Can you check the value of uxCriticalNesting both on entry into main() and immediately before starting the scheduler. uxCriticalNesting is defined in port.c, but I’m not sure which compiler you are using. You will find port.c in FreeRTOS/source/portable/[compiler]/ARM_CM3 (or ARM_CM4F). It should be non zero (probably 0xaaaaaaaa) when you enter main, and close to the same value before the scheduler is started. If the start up code was not executing properly you may find it had a different value.

Regards.

pierreculot wrote on Friday, July 11, 2014:

Hi Richard,
Yes including any of these lines. The first one is enough to stop the DMA.
I’m on GCC.

I checked uxCriticalNesting and it is not modified so far I can reach because the program loops in DMA_GetCurrDataCounter() under SendOnUsart1().
Then it doesn’t reach vTaskStartScheduler().

I checked with the DMA disabled and, the uxCriticalNesting variable is not modified before the scheduler starts.

May be I must check all the SFR to see a possible change.

rtel wrote on Friday, July 11, 2014:

because the program loops in DMA_GetCurrDataCounter() under SendOnUsart1().
Then it doesn’t reach vTaskStartScheduler().

Ah! So you are trying to use the UART DMA interrupts before the scheduler has been started. That makes much more sense then.

FreeRTOS will deliberately leave interrupts at and below configMAX_SYSCALL_INTERRUPT_PRIORITY masked until the scheduler has started. This is done to ensure interrupts do not try to use a FreeRTOS API function while the scheduler is in an inconsistent state. When you call the first FreeRTOS API function interrupts will be enabled, but when you come out they will be masked (still enabled, but masked to a certain priority level). Hence the interrupt stops working.

The interrupts are automatically unmasked when the scheduler is started (when the tasks start running).

Regards.

pierreculot wrote on Saturday, July 19, 2014:

OK now.
First I start a “main task” and the scheduler. So FreeRTOS runs before interrupt.
At the end of the main task I delete it.

Thank you