如何在 ESP32 的第二个核心上初始化队列?

How to initialize a Queue on a second core of an ESP32?

目前我正在开发一个演示程序以更好地理解使用 FreeRTOS。因此我想尝试在我的第二个核心(core1)上初始化一个队列。初始化后,我想在 1 秒的间隔内向它添加一些东西,每当没有任何反应时,我想检查我的队列并关闭它的内容。与该队列相关的所有内容都应该在第二个核心上运行。原因是我之前在主核心上运行的 Web 服务器上工作。我未来的队列应该在第二个核心上并行工作。

这是我当前的演示程序:

#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "freertos/timers.h"
#include "esp_system.h"

    xQueueHandle queue;



void taskqueuecreator()
{
 queue = xQueueCreate(15, sizeof(int));
 printf("Queue created on core %d!\n", xPortGetCoreID());

 vTaskDelete(NULL);

}

void addspitoqueue(){

    while(true){
        printf("added Item to Queue");
        xQueueSend(queue, 1, 1000 / portTICK_PERIOD_MS);
        vTaskDelay(1000 / portTICK_PERIOD_MS);
    }
}



void TimerStateMachine(int Methodnum){

    switch(Methodnum){
        case 1:
        printf("SPI communication with arm happens here %d \n",xPortGetCoreID());
        break;

        case 2:
        printf("something else is about to happen here");
        break;


        return;
    }



}

void queueloop(){
     int receivedint = 0; //1 = spi communication mit Arm
    while(true){
        printf("in queueloop");
        if(xQueueReceive(queue, &receivedint, 5000)){
        TimerStateMachine(receivedint);
        }
    }
}



void app_main(void)
{




xTaskCreatePinnedToCore(&taskqueuecreator, "create queue", 4*1024, NULL, 2, NULL, 1 );
printf("\n task done\n");
xTaskCreatePinnedToCore(&addspitoqueue, "create spitask", 4*1024, NULL, 2, NULL, 1);
printf("\n task done part 2\n");
xTaskCreatePinnedToCore(&queueloop, "queue loop", 4*1024, NULL, 2, NULL, 1);
printf("\n task done part 3\n");

}

执行它时,我收到以下错误消息,然后重置:

ets Jul 29 2019 12:21:46

rst:0xc (SW_CPU_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT) configsip: 0, SPIWP:0xee clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00 mode:DIO, clock div:2 load:0x3fff0030,len:7028 load:0x40078000,len:14308 load:0x40080400,len:3716 0x40080400: _init at ??:?

entry 0x40080680 I (27) boot: ESP-IDF v4.3.1-dirty 2nd stage bootloader I (27) boot: compile time 10:17:24 I (27) boot: chip revision: 3 I (30) boot_comm: chip revision: 3, min. bootloader chip revision: 0 I (38) boot.esp32: SPI Speed : 40MHz I (42) boot.esp32: SPI Mode : DIO I (47) boot.esp32: SPI Flash Size : 8MB I (51) boot: Enabling RNG early entropy source... I (57) boot: Partition Table: I (60) boot: ## Label Usage Type ST Offset Length I (68) boot: 0 nvs WiFi data
01 02 00009000 00006000 I (75) boot: 1 phy_init RF data
01 01 0000f000 00001000 I (82) boot: 2 factory factory app
00 00 00010000 00100000 I (90) boot: End of partition table I (94) boot_comm: chip revision: 3, min. application chip revision: 0 I (101) esp_image: segment 0: paddr=00010020 vaddr=3f400020 size=06964h ( 26980) map I (120) esp_image: segment 1: paddr=0001698c vaddr=3ffb0000 size=028dch ( 10460) load I (124) esp_image: segment 2: paddr=00019270 vaddr=40080000 size=06da8h ( 28072) load I (138) esp_image: segment 3: paddr=00020020 vaddr=400d0020 size=135bch ( 79292) map I (167) esp_image: segment 4: paddr=000335e4 vaddr=40086da8 size=03fb0h ( 16304) load I (174) esp_image: segment 5: paddr=0003759c vaddr=50000000 size=00010h ( 16) load I (180) boot: Loaded app from partition at offset 0x10000 I (180) boot: Disabling RNG early entropy source... I (196) cpu_start: Pro cpu up. I (196) cpu_start: Starting app cpu, entry point is 0x40080ffc 0x40080ffc: call_start_cpu1 at C:/Users/Student/esp/esp-idf/components/esp_system/port/cpu_start.c:141

I (183) cpu_start: App cpu up. I (210) cpu_start: Pro cpu start user code I (210) cpu_start: cpu freq: 160000000 I (210) cpu_start: Application information: I (215) cpu_start: Project name: main I (220) cpu_start: App version: 1 I (224) cpu_start: Compile time: Jan 3 2022 15:11:19 I (230) cpu_start: ELF file SHA256: 65b119d32e9f73f6... I (236) cpu_start: ESP-IDF: v4.3.1-dirty I (242) heap_init: Initializing. RAM available for dynamic allocation: I (249) heap_init: At 3FFAE6E0 len 00001920 (6 KiB): DRAM I (255) heap_init: At 3FFB31A8 len 0002CE58 (179 KiB): DRAM I (261) heap_init: At 3FFE0440 len 00003AE0 (14 KiB): D/IRAM I (267) heap_init: At 3FFE4350 len 0001BCB0 (111 KiB): D/IRAM I (274) heap_init: At 4008AD58 len 000152A8 (84 KiB): IRAM I (281) spi_flash: detected chip: generic I (285) spi_flash: flash io: dio I (290) cpu_start: Starting scheduler on PRO CPU. I (0) cpu_start: Starting scheduler on APP CPU.

task done

Queue created on core 1!

task done part 2

Guru Meditation Error: Core 1 panic'ed (LoadProhibited). Exception was unhandled.

Core 1 register dump: PC : 0x4000c344 PS : 0x00060633 A0 : 0x80085685 A1 : 0x3ffb95e0 A2 : 0x3ffaffa8 A3 : 0x00000000 A4 : 0x00000004 A5 : 0x3ffaffa8 A6 : 0x00000001 A7 : 0x00000000 A8 : 0x40000000 A9 : 0x3ffb92a0 A10 : 0x3ffb92c0 A11 : 0x00000001 A12 : 0x3ffb9524 A13 : 0x3ffaef6c A14 : 0x00000000 A15 : 0x00000001 SAR : 0x00000008 EXCCAUSE: 0x0000001c EXCVADDR: 0x00000000 LBEG : 0x400014fd LEND : 0x4000150d LCOUNT : 0xffffffff

Backtrace:0x4000c341:0x3ffb95e0 0x40085682:0x3ffb95f0 0x40085b0e:0x3ffb9610 0x400d40d0:0x3ffb9650 0x40087b39:0x3ffb9670 0x40085682: prvCopyDataToQueue at C:/Users/Student/esp/esp-idf/components/freertos/queue.c:2114

0x40085b0e: xQueueGenericSend at C:/Users/Student/esp/esp-idf/components/freertos/queue.c:804

0x400d40d0: addspitoqueue at C:\Users\Student\Projekte\sample_project\build/../main/main.c:30 (discriminator 1)

0x40087b39: vPortTaskWrapper at C:/Users/Student/esp/esp-idf/components/freertos/port/xtensa/port.c:168

ELF file SHA256: 65b119d32e9f73f6

Rebooting...

我假设(但我不是 100% 确定)这是由这条线引起的

xQueueHandle queue;

正在核心0和这部分执行

while(true){
    printf("added Item to Queue");
    xQueueSend(queue, 1, 1000 / portTICK_PERIOD_MS);
    vTaskDelay(1000 / portTICK_PERIOD_MS);
}

正在核心 1 上执行。

如果是这样,有人可能知道如何解决该问题吗? 如果没有,有人知道出了什么问题吗?

你不需要假设问题出在哪里;答案在您发布的回溯中。异常发生在您代码中的特定函数调用期间:

0x400d40d0: addspitoqueue at C:\Users\Student\Projekte\sample_project\build/../main/main.c:30

你的函数addspitoqueue()是:

void addspitoqueue(){

    while(true){
        printf("added Item to Queue");
        xQueueSend(queue, 1, 1000 / portTICK_PERIOD_MS);
        vTaskDelay(1000 / portTICK_PERIOD_MS);
    }
}

具体是这一行导致了问题:

        xQueueSend(queue, 1, 1000 / portTICK_PERIOD_MS);

看看xQueueSend()的定义:

 BaseType_t xQueueSend(
                            QueueHandle_t xQueue,
                            const void * pvItemToQueue,
                            TickType_t xTicksToWait
                         );

它的意思是获取指向要放置在队列中的对象的指针 - 而不是值。它会将对象复制到从您传递的地址开始的队列中 - 在本例中,1,这肯定会导致崩溃。

您需要将值存储在 int 中(因为您将队列定义为 sizeof(int) 对象的队列),然后将指针传递到存储位置。

例如:

static int value_to_queue;

void addspitoqueue(){

    while(true){
        printf("added Item to Queue");
        value_to_queue = 1;
        xQueueSend(queue, &value_to_queue, 1000 / portTICK_PERIOD_MS);
        vTaskDelay(1000 / portTICK_PERIOD_MS);
    }
}