hello,
I using DMA (Stm32F103) with RTOS. I just want to print 2 strings according to running tasks. Following is the code snippet. Problem is on terminal window it only shows Task 2 running if i am not using breakpoint in both tasks. But if I use breakpoint in both tasks then output is fine. Snapshots of outputs are below.
Regards, pavel
int main(void)
{
/* Configure the system clock to 72 MHz */
SystemClock_Config();
/* Initialize LED2 */
LED_Init();
/* Wait for the end of the transfer and check received data */
//WaitAndCheckEndOfTransfer();
/* Before a semaphore is used it must be explicitly created. In this example a
mutex type semaphore is created. */
xMutex = xSemaphoreCreateMutex();
/* Check the semaphore was created successfully before creating the tasks. */
if( xMutex != NULL )
{
/* Create one of the two tasks. Note that a real application should check
the return value of the xTaskCreate() call to ensure the task was created
successfully. */
xTaskCreate( vTaskFunction1, /* Pointer to the function that implements the task. */
"Task 1",/* Text name for the task. This is to facilitate
debugging only. */
configMINIMAL_STACK_SIZE, /* Stack depth - small microcontrollers will use much
less stack than this. */
(void*)str1, /* This example does not use the task parameter. */
1, /* This task will run at priority 1. */
NULL ); /* This example does not use the task handle. */
/* Create the other task in exactly the same way and at the same priority. */
xTaskCreate( vTaskFunction2, "Task 2", configMINIMAL_STACK_SIZE, (void*)pcTextForTask2, 2, NULL );
xTaskCreate( initTask, "Task 0", configMINIMAL_STACK_SIZE, NULL, 3, initTaskHandle );
/* Start the scheduler so the tasks start executing. */
vTaskStartScheduler();
/* If all is well then main() will never reach here as the scheduler will
now be running the tasks. If main() does reach here then it is likely that
there was insufficient heap memory available for the idle task to be created.
Chapter 2 provides more information on heap memory management. */
for( ;; );
}
}
void initTask( void *pvParameters )
{
/* As per most tasks, this task is implemented in an infinite loop. */
for( ;; )
{
/* Initialize button in EXTI mode */
UserButton_Init();
/* Configure USARTx (USART IP configuration and related GPIO initialization) */
Configure_USART();
/* Configure DMA channels for USART instance */
Configure_DMA();
/* Wait for User push-button press to start transfer */
//WaitForUserButtonPress();
/* Initiate DMA transfers */
StartTransfers();
vTaskDelete( initTaskHandle );
}
}
void vTaskFunction1( void *pvParameters )
{
char *pcTaskName;
const TickType_t xDelay250ms = pdMS_TO_TICKS( 250 );
/* The string to print out is passed in via the parameter. Cast this to a
character pointer. */
pcTaskName = ( char * ) pvParameters;
/* As per most tasks, this task is implemented in an infinite loop. */
for( ;; )
{
ubNbDataToTransmit = 16;
if (xSemaphoreTake(xMutex, 10))
{
user_uart_tx(pcTaskName, ubNbDataToTransmit);
if (xSemaphoreGive(xMutex) != pdTRUE)
{
/* Processing Error */
LED_Blinking(LED_BLINK_ERROR);
}
}
//vPrintString(pcTaskName);
/* Delay for a period. This time a call to vTaskDelay() is used which places
the task into the Blocked state until the delay period has expired. The
parameter takes a time specified in ‘ticks’, and the pdMS_TO_TICKS() macro
is used (where the xDelay250ms constant is declared) to convert 250
milliseconds into an equivalent time in ticks. */
vTaskDelay( xDelay250ms );
}
}
void vTaskFunction2( void *pvParameters )
{
char *pcTaskName;
const TickType_t xDelay250ms = pdMS_TO_TICKS( 250 );
/* The string to print out is passed in via the parameter. Cast this to a
character pointer. */
pcTaskName = ( char * ) pvParameters;
/* As per most tasks, this task is implemented in an infinite loop. */
for( ;; )
{
ubNbDataToTransmit = 20;
if (xSemaphoreTake(xMutex, 10))
{
user_uart_tx(pcTaskName, ubNbDataToTransmit);
if (xSemaphoreGive(xMutex) != pdTRUE)
{
/* Processing Error */
LED_Blinking(LED_BLINK_ERROR);
}
}
//vPrintString(pcTaskName);
/* Delay for a period. This time a call to vTaskDelay() is used which places
the task into the Blocked state until the delay period has expired. The
parameter takes a time specified in ‘ticks’, and the pdMS_TO_TICKS() macro
is used (where the xDelay250ms constant is declared) to convert 250
milliseconds into an equivalent time in ticks. */
vTaskDelay( xDelay250ms );
}
}
void Configure_DMA(void)
{
/* DMA1 used for USART2 Transmission and Reception
*/
/* (1) Enable the clock of DMA1 */
LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_DMA1);
/* (2) Configure NVIC for DMA transfer complete/error interrupts */
NVIC_SetPriority(DMA1_Channel7_IRQn, 6);
NVIC_EnableIRQ(DMA1_Channel7_IRQn);
NVIC_SetPriority(DMA1_Channel6_IRQn, 7);
NVIC_EnableIRQ(DMA1_Channel6_IRQn);
/* (3) Configure the DMA functional parameters for transmission */
LL_DMA_ConfigTransfer(DMA1, LL_DMA_CHANNEL_7,
LL_DMA_DIRECTION_MEMORY_TO_PERIPH |
LL_DMA_PRIORITY_HIGH |
LL_DMA_MODE_NORMAL |
LL_DMA_PERIPH_NOINCREMENT |
LL_DMA_MEMORY_INCREMENT |
LL_DMA_PDATAALIGN_BYTE |
LL_DMA_MDATAALIGN_BYTE);
LL_DMA_ConfigAddresses(DMA1, LL_DMA_CHANNEL_7,
(uint32_t)aTxBuffer,
LL_USART_DMA_GetRegAddr(USART2),
LL_DMA_GetDataTransferDirection(DMA1, LL_DMA_CHANNEL_7));
LL_DMA_SetDataLength(DMA1, LL_DMA_CHANNEL_7, ubNbDataToTransmit);
/* (4) Configure the DMA functional parameters for reception */
LL_DMA_ConfigTransfer(DMA1, LL_DMA_CHANNEL_6,
LL_DMA_DIRECTION_PERIPH_TO_MEMORY |
LL_DMA_PRIORITY_HIGH |
LL_DMA_MODE_NORMAL |
LL_DMA_PERIPH_NOINCREMENT |
LL_DMA_MEMORY_INCREMENT |
LL_DMA_PDATAALIGN_BYTE |
LL_DMA_MDATAALIGN_BYTE);
LL_DMA_ConfigAddresses(DMA1, LL_DMA_CHANNEL_6,
LL_USART_DMA_GetRegAddr(USART2),
(uint32_t)aRxBuffer,
LL_DMA_GetDataTransferDirection(DMA1, LL_DMA_CHANNEL_6));
LL_DMA_SetDataLength(DMA1, LL_DMA_CHANNEL_6, ubNbDataToReceive);
/* (5) Enable DMA transfer complete/error interrupts */
LL_DMA_EnableIT_TC(DMA1, LL_DMA_CHANNEL_7);
LL_DMA_EnableIT_TE(DMA1, LL_DMA_CHANNEL_7);
LL_DMA_EnableIT_TC(DMA1, LL_DMA_CHANNEL_6);
LL_DMA_EnableIT_TE(DMA1, LL_DMA_CHANNEL_6);
}