sdk例程‐freertos - minichao9901/TangNano-20k-Zynq-7020 GitHub Wiki
例程
- 创建2个task,一个是生成者,发送hello_world_?的字符串,这里?是发送TxtaskCntr。接收者接收这个字符串。
- 通过Queue发送数据
- 生产者task速度为2s/次,消费者速度是3s/次
- 额外创建一个Timer,设置为一次性的。当Timer到期后,关闭2个Task。
分析
- 从以上例程看,生产者快于消费者,Queue会满,这个时候如果生产者不停止生成,那么就会溢出。
- 这个时候xQueueSend的第3个参数是blocktime时间,就非常关键了。如果blocktime=0,那么生产者会继续生产,就是会溢出。结果如下,会遗漏数据:
![image](https://github.com/minichao9901/TangNano-20k-Zynq-7020/assets/61445559/883880d1-490f-40ec-a675-9507415deabe)
- 如果设置blocktime=portMAX_DELAY/10,这个时间非常大,不会溢出了。那么只要Queue满了,就会自动block,停止发送,直到Queue为空。结果如下,不会遗漏数据:
![image](https://github.com/minichao9901/TangNano-20k-Zynq-7020/assets/61445559/3c1adf14-aa4e-4728-8b1d-2c0cf010f955)
附代码
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "timers.h"
/* Xilinx includes. */
#include "xil_printf.h"
#include "xparameters.h"
#include "stdio.h"
#define TIMER_ID 1
#define DELAY_100_SECONDS 100000UL
#define DELAY_2_SECOND 2000UL
#define DELAY_3_SECOND 3000UL
#define TIMER_CHECK_THRESHOLD 300
/*-----------------------------------------------------------*/
/* The Tx and Rx tasks as described at the top of this file. */
static void prvTxTask( void *pvParameters );
static void prvRxTask( void *pvParameters );
static void vTimerCallback( TimerHandle_t pxTimer );
/*-----------------------------------------------------------*/
/* The queue used by the Tx and Rx tasks, as described at the top of this
file. */
static TaskHandle_t xTxTask;
static TaskHandle_t xRxTask;
static QueueHandle_t xQueue = NULL;
static TimerHandle_t xTimer = NULL;
char HWstring[15] = "Hello World";
long RxtaskCntr = 0;
long TxtaskCntr = 0;
int main( void )
{
const TickType_t x100seconds = pdMS_TO_TICKS( DELAY_100_SECONDS );
xil_printf( "Hello from Freertos example main\r\n" );
/* Create the two tasks. The Tx task is given a lower priority than the
Rx task, so the Rx task will leave the Blocked state and pre-empt the Tx
task as soon as the Tx task places an item in the queue. */
xTaskCreate( prvTxTask, /* The function that implements the task. */
( const char * ) "Tx", /* Text name for the task, provided to assist debugging only. */
1000, /* The stack allocated to the task. */
NULL, /* The task parameter is not used, so set to NULL. */
3, /* The task runs at the idle priority. */
&xTxTask );
xTaskCreate( prvRxTask,
( const char * ) "GB",
1000,
NULL,
3 -1,
&xRxTask );
/* Create the queue used by the tasks. The Rx task has a higher priority
than the Tx task, so will preempt the Tx task and remove values from the
queue as soon as the Tx task writes to the queue - therefore the queue can
never have more than one item in it. */
xQueue = xQueueCreate( 4, /* There is only one space in the queue. */
sizeof( HWstring ) ); /* Each space in the queue is large enough to hold a uint32_t. */
/* Check the queue was created. */
configASSERT( xQueue );
/* Create a timer with a timer expiry of 10 seconds. The timer would expire
after 10 seconds and the timer call back would get called. In the timer call back
checks are done to ensure that the tasks have been running properly till then.
The tasks are deleted in the timer call back and a message is printed to convey that
the example has run successfully.
The timer expiry is set to 10 seconds and the timer set to not auto reload. */
xTimer = xTimerCreate( (const char *) "Timer",
x100seconds,
pdFALSE,
(void *) TIMER_ID,
vTimerCallback);
/* Check the timer was created. */
configASSERT( xTimer );
/* start the timer with a block time of 0 ticks. This means as soon
as the schedule starts the timer will start running and will expire after
10 seconds */
xTimerStart( xTimer, 0 );
/* Start the tasks and timer running. */
vTaskStartScheduler();
/* If all is well, the scheduler will now be running, and the following line
will never be reached. If the following line does execute, then there was
insufficient FreeRTOS heap memory available for the idle and/or timer tasks
to be created. See the memory management section on the FreeRTOS web site
for more details. */
for( ;; );
}
/*-----------------------------------------------------------*/
static void prvTxTask( void *pvParameters )
{
const TickType_t x2second = pdMS_TO_TICKS( DELAY_2_SECOND );
char s[100]="";
for( ;; )
{
/* Delay for 1 second. */
vTaskDelay( x2second );
sprintf(s, "%s_%d", HWstring, (int)TxtaskCntr);
/* Send the next value on the queue. The queue should always be
empty at this point so a block time of 0 is used. */
xQueueSend( xQueue, /* The queue being written to. */
s, /* The address of the data being sent. */
portMAX_DELAY/10 ); /* The block time. */
TxtaskCntr++;
}
}
/*-----------------------------------------------------------*/
static void prvRxTask( void *pvParameters )
{
char Recdstring[15] = "";
const TickType_t x3second = pdMS_TO_TICKS( DELAY_3_SECOND );
for( ;; )
{
vTaskDelay( x3second );
/* Block to wait for data arriving on the queue. */
xQueueReceive( xQueue, /* The queue being read. */
Recdstring, /* Data is read into this address. */
portMAX_DELAY ); /* Wait without a timeout for data. */
/* Print the received data. */
xil_printf( "Rx task received string from Tx task: %s\r\n", Recdstring );
RxtaskCntr++;
}
}
/*-----------------------------------------------------------*/
static void vTimerCallback( TimerHandle_t pxTimer )
{
long lTimerId;
configASSERT( pxTimer );
lTimerId = ( long ) pvTimerGetTimerID( pxTimer );
if (lTimerId != TIMER_ID) {
xil_printf("FreeRTOS Hello World Example FAILED");
}
/* If the RxtaskCntr is updated every time the Rx task is called. The
Rx task is called every time the Tx task sends a message. The Tx task
sends a message every 1 second.
The timer expires after 10 seconds. We expect the RxtaskCntr to at least
have a value of 9 (TIMER_CHECK_THRESHOLD) when the timer expires. */
if (RxtaskCntr >= TIMER_CHECK_THRESHOLD) {
xil_printf("FreeRTOS Hello World Example PASSED");
} else {
xil_printf("FreeRTOS Hello World Example FAILED");
}
vTaskDelete( xRxTask );
vTaskDelete( xTxTask );
}