FreeRTOS:队列未按预期工作
FreeRTOS: Queue did not work as expected
我是 FreeRTOS 新手。我写了一个使用队列在任务之间传输数据的例子。然而,显示的结果是错误的。谁能帮我解决这个问题?
谢谢!
要显示的变量:
unsigned int temperatureRaw = 25;
unsigned int flowRateRaw = 30;
unsigned int carbonLevelRaw = 250;
unsigned int salinityLevelRaw = 75;
包含指向上述变量的指针的结构:
struct RawData {
unsigned int *temperatureRaw;
unsigned int *flowRateRaw;
unsigned int *carbonLevelRaw;
unsigned int *salinityLevelRaw;
};
typedef struct RawData RawData;
任务原型
static void vOLEDTask( void *pvParameters );
static void vTask1( void *pvParameters );
static void prvSetupHardware( void );
队列句柄:
QueueHandle_t xOLEDQueue, xRawQueue;
主要:
int main( void )
{
prvSetupHardware();
/* Create queues */
xOLEDQueue = xQueueCreate( mainOLED_QUEUE_SIZE, sizeof( xOLEDMessage * ) );
xRawQueue = xQueueCreate( 3, sizeof( RawData * ) );
/* Check if queues are successfully created */
if( ( xOLEDQueue != 0 ) && ( xRawQueue != 0 ) ) {
// Declare variables
RawData xRawData = { &temperatureRaw, &flowRateRaw, &carbonLevelRaw, &salinityLevelRaw };
RawData *pxRawData = &xRawData;
/* Start the tasks defined within this file/specific to this demo. */
xTaskCreate( vOLEDTask, "OLED", mainOLED_TASK_STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL );
xTaskCreate( vTask1, "Task1", 1000, ( void * )pxRawData, 1, NULL );
/* Start the scheduler. */
vTaskStartScheduler();
}
return 0;
}
任务定义:
void prvSetupHardware( void )
{
/* If running on Rev A2 silicon, turn the LDO voltage up to 2.75V. This is
a workaround to allow the PLL to operate reliably. */
if( DEVICE_IS_REVA2 )
{
SysCtlLDOSet( SYSCTL_LDO_2_75V );
}
/* Set the clocking to run from the PLL at 50 MHz */
SysCtlClockSet( SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_8MHZ );
}
void vOLEDTask( void *pvParameters )
{
RawData *pxRawData = NULL;
unsigned long ulMaxY;
static char cMessage[ mainMAX_MSG_LEN ];
extern volatile unsigned long ulMaxJitter;
const unsigned char *pucImage;
/* Functions to access the OLED. The one used depends on the dev kit
being used. */
void ( *vOLEDInit )( unsigned long ) = NULL;
void ( *vOLEDStringDraw )( const char *, unsigned long, unsigned long, unsigned char ) = NULL;
void ( *vOLEDImageDraw )( const unsigned char *, unsigned long, unsigned long, unsigned long, unsigned long ) = NULL;
void ( *vOLEDClear )( void ) = NULL;
/* Map the OLED access functions to the driver functions that are appropriate
for the evaluation kit being used. */
switch( HWREG( SYSCTL_DID1 ) & SYSCTL_DID1_PRTNO_MASK )
{
case SYSCTL_DID1_PRTNO_6965 :
case SYSCTL_DID1_PRTNO_2965 : vOLEDInit = OSRAM128x64x4Init;
vOLEDStringDraw = OSRAM128x64x4StringDraw;
vOLEDImageDraw = OSRAM128x64x4ImageDraw;
vOLEDClear = OSRAM128x64x4Clear;
ulMaxY = mainMAX_ROWS_64;
pucImage = pucBasicBitmap;
break;
case SYSCTL_DID1_PRTNO_1968 :
case SYSCTL_DID1_PRTNO_8962 : vOLEDInit = RIT128x96x4Init;
vOLEDStringDraw = RIT128x96x4StringDraw;
vOLEDImageDraw = RIT128x96x4ImageDraw;
vOLEDClear = RIT128x96x4Clear;
ulMaxY = mainMAX_ROWS_96;
pucImage = pucBasicBitmap;
break;
default : vOLEDInit = vFormike128x128x16Init;
vOLEDStringDraw = vFormike128x128x16StringDraw;
vOLEDImageDraw = vFormike128x128x16ImageDraw;
vOLEDClear = vFormike128x128x16Clear;
ulMaxY = mainMAX_ROWS_128;
pucImage = pucGrLibBitmap;
break;
}
/* Initialise the OLED and display a startup message. */
vOLEDInit( ulSSI_FREQUENCY );
for( ;; )
{
xQueueReceive( xRawQueue, ( void * )&pxRawData, portMAX_DELAY );
/* Display the message. */
sprintf( cMessage, "%s %u C", "Temperature", *(pxRawData->temperatureRaw) );
vOLEDStringDraw( cMessage, 0, 10, mainFULL_SCALE );
sprintf( cMessage, "%s %u LPS", "Flow Rate", *(pxRawData->flowRateRaw) );
vOLEDStringDraw( cMessage, 0, 20, mainFULL_SCALE );
sprintf( cMessage, "%s %u ppm", "Carbon Level", *(pxRawData->carbonLevelRaw) );
vOLEDStringDraw( cMessage, 0, 30, mainFULL_SCALE );
sprintf( cMessage, "%s %u ppt", "Salinity Level", *(pxRawData->salinityLevelRaw) );
vOLEDStringDraw( cMessage, 0, 40, mainFULL_SCALE );
}
}
/*-----------------------------------------------------------*/
static void vTask1( void *pvParameters )
{
RawData *pxRawData = ( RawData * )pvParameters;
for( ;; ) {
xQueueSend( xRawQueue, ( void * )&pxRawData, portMAX_DELAY );
vTaskDelay( 1000/portTICK_RATE_MS );
}
}
我没有研究所有代码,但我看到的第一个问题是你将 pxRawData 作为参数传递给任务,pxRawData 是指向 xRawData 的指针,但 xRawData 的块范围非常窄,并且它声明的堆栈与任务使用的堆栈不同,因此当任务开始时指向的变量将不存在 运行 - 或者如果它确实存在,那是幸运的,并且存在它会存在的风险被覆盖(取决于正在使用的 FreeRTOS port)。
此外,考虑到创建 xRawQueue 是为了保存指向 RawData 的指针,但我认为您在 vTask1 中对 xQueueSend 的调用正在传递指针的地址,因此它正在排队指向指向 RawData 的指针的指针,而不是指向 RawData 的指针。虽然这可能并不重要,因为它也被接收到指向指针的指针中,然后被这样访问。
我是 FreeRTOS 新手。我写了一个使用队列在任务之间传输数据的例子。然而,显示的结果是错误的。谁能帮我解决这个问题?
谢谢!
要显示的变量:
unsigned int temperatureRaw = 25;
unsigned int flowRateRaw = 30;
unsigned int carbonLevelRaw = 250;
unsigned int salinityLevelRaw = 75;
包含指向上述变量的指针的结构:
struct RawData {
unsigned int *temperatureRaw;
unsigned int *flowRateRaw;
unsigned int *carbonLevelRaw;
unsigned int *salinityLevelRaw;
};
typedef struct RawData RawData;
任务原型
static void vOLEDTask( void *pvParameters );
static void vTask1( void *pvParameters );
static void prvSetupHardware( void );
队列句柄:
QueueHandle_t xOLEDQueue, xRawQueue;
主要:
int main( void )
{
prvSetupHardware();
/* Create queues */
xOLEDQueue = xQueueCreate( mainOLED_QUEUE_SIZE, sizeof( xOLEDMessage * ) );
xRawQueue = xQueueCreate( 3, sizeof( RawData * ) );
/* Check if queues are successfully created */
if( ( xOLEDQueue != 0 ) && ( xRawQueue != 0 ) ) {
// Declare variables
RawData xRawData = { &temperatureRaw, &flowRateRaw, &carbonLevelRaw, &salinityLevelRaw };
RawData *pxRawData = &xRawData;
/* Start the tasks defined within this file/specific to this demo. */
xTaskCreate( vOLEDTask, "OLED", mainOLED_TASK_STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL );
xTaskCreate( vTask1, "Task1", 1000, ( void * )pxRawData, 1, NULL );
/* Start the scheduler. */
vTaskStartScheduler();
}
return 0;
}
任务定义:
void prvSetupHardware( void )
{
/* If running on Rev A2 silicon, turn the LDO voltage up to 2.75V. This is
a workaround to allow the PLL to operate reliably. */
if( DEVICE_IS_REVA2 )
{
SysCtlLDOSet( SYSCTL_LDO_2_75V );
}
/* Set the clocking to run from the PLL at 50 MHz */
SysCtlClockSet( SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_8MHZ );
}
void vOLEDTask( void *pvParameters )
{
RawData *pxRawData = NULL;
unsigned long ulMaxY;
static char cMessage[ mainMAX_MSG_LEN ];
extern volatile unsigned long ulMaxJitter;
const unsigned char *pucImage;
/* Functions to access the OLED. The one used depends on the dev kit
being used. */
void ( *vOLEDInit )( unsigned long ) = NULL;
void ( *vOLEDStringDraw )( const char *, unsigned long, unsigned long, unsigned char ) = NULL;
void ( *vOLEDImageDraw )( const unsigned char *, unsigned long, unsigned long, unsigned long, unsigned long ) = NULL;
void ( *vOLEDClear )( void ) = NULL;
/* Map the OLED access functions to the driver functions that are appropriate
for the evaluation kit being used. */
switch( HWREG( SYSCTL_DID1 ) & SYSCTL_DID1_PRTNO_MASK )
{
case SYSCTL_DID1_PRTNO_6965 :
case SYSCTL_DID1_PRTNO_2965 : vOLEDInit = OSRAM128x64x4Init;
vOLEDStringDraw = OSRAM128x64x4StringDraw;
vOLEDImageDraw = OSRAM128x64x4ImageDraw;
vOLEDClear = OSRAM128x64x4Clear;
ulMaxY = mainMAX_ROWS_64;
pucImage = pucBasicBitmap;
break;
case SYSCTL_DID1_PRTNO_1968 :
case SYSCTL_DID1_PRTNO_8962 : vOLEDInit = RIT128x96x4Init;
vOLEDStringDraw = RIT128x96x4StringDraw;
vOLEDImageDraw = RIT128x96x4ImageDraw;
vOLEDClear = RIT128x96x4Clear;
ulMaxY = mainMAX_ROWS_96;
pucImage = pucBasicBitmap;
break;
default : vOLEDInit = vFormike128x128x16Init;
vOLEDStringDraw = vFormike128x128x16StringDraw;
vOLEDImageDraw = vFormike128x128x16ImageDraw;
vOLEDClear = vFormike128x128x16Clear;
ulMaxY = mainMAX_ROWS_128;
pucImage = pucGrLibBitmap;
break;
}
/* Initialise the OLED and display a startup message. */
vOLEDInit( ulSSI_FREQUENCY );
for( ;; )
{
xQueueReceive( xRawQueue, ( void * )&pxRawData, portMAX_DELAY );
/* Display the message. */
sprintf( cMessage, "%s %u C", "Temperature", *(pxRawData->temperatureRaw) );
vOLEDStringDraw( cMessage, 0, 10, mainFULL_SCALE );
sprintf( cMessage, "%s %u LPS", "Flow Rate", *(pxRawData->flowRateRaw) );
vOLEDStringDraw( cMessage, 0, 20, mainFULL_SCALE );
sprintf( cMessage, "%s %u ppm", "Carbon Level", *(pxRawData->carbonLevelRaw) );
vOLEDStringDraw( cMessage, 0, 30, mainFULL_SCALE );
sprintf( cMessage, "%s %u ppt", "Salinity Level", *(pxRawData->salinityLevelRaw) );
vOLEDStringDraw( cMessage, 0, 40, mainFULL_SCALE );
}
}
/*-----------------------------------------------------------*/
static void vTask1( void *pvParameters )
{
RawData *pxRawData = ( RawData * )pvParameters;
for( ;; ) {
xQueueSend( xRawQueue, ( void * )&pxRawData, portMAX_DELAY );
vTaskDelay( 1000/portTICK_RATE_MS );
}
}
我没有研究所有代码,但我看到的第一个问题是你将 pxRawData 作为参数传递给任务,pxRawData 是指向 xRawData 的指针,但 xRawData 的块范围非常窄,并且它声明的堆栈与任务使用的堆栈不同,因此当任务开始时指向的变量将不存在 运行 - 或者如果它确实存在,那是幸运的,并且存在它会存在的风险被覆盖(取决于正在使用的 FreeRTOS port)。
此外,考虑到创建 xRawQueue 是为了保存指向 RawData 的指针,但我认为您在 vTask1 中对 xQueueSend 的调用正在传递指针的地址,因此它正在排队指向指向 RawData 的指针的指针,而不是指向 RawData 的指针。虽然这可能并不重要,因为它也被接收到指向指针的指针中,然后被这样访问。