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 的指针。虽然这可能并不重要,因为它也被接收到指向指针的指针中,然后被这样访问。