FreeRTOS: очередь не работает должным образом

Я новичок в 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 );
  }
}

person Đạt Ngô    schedule 02.12.2015    source источник


Ответы (1)


Я не изучил весь код, но первая проблема, которую я вижу, заключается в том, что вы передаете pxRawData в качестве параметра задачи, pxRawData - это указатель на xRawData, но xRawData имеет очень узкую область видимости блока и стек, в котором он объявлен. отличается от стека, используемого задачей, поэтому указанная переменная не будет существовать, когда задача запускается - или, если она существует, то по счастливой случайности, и есть риск, что она будет перезаписана (в зависимости от используется порт FreeRTOS).

Также учтите, что xRawQueue создан для хранения указателей на RawData, но я думаю, что ваш вызов xQueueSend в vTask1 передает адрес указателя, поэтому он ставит в очередь указатель на указатель на RawData, а не на указатель на RawData. Хотя это, вероятно, не имеет значения, поскольку он также получен в указатель на указатель, а затем доступен как таковой.

person Richard    schedule 02.12.2015
comment
Спасибо за комментарий! Я перемещаю объявление xRawData и pxRawData за пределы основной области видимости как глобальные переменные, и мой код работает правильно. Кроме того, в соответствии с определением xQueueSend (), второй параметр - это указатель на элемент, который должен быть помещен в очередь. Следовательно, поэтому я передал указатель на указатель на RawData, поскольку xRawQueue содержит указатели на RawData. - person Đạt Ngô; 02.12.2015