Reputation: 21
I'm developing high frequency DAQ based on ESP32 and freeRTOS.There will be 2 task, first task will run on core 0, communicating with sensors to collect data at 4000SPS, using SPI bus. Task 2 will run on core 1, receiving data from first task and send it async over TCP. Ideally, task 2 should send data while task 1 collecting latest one, simultaneously (dual core, right?)
When I do a test run, I let SPI bus run as fast as possible, but it just keep blocking task 2 from ever running!! I don't want to use vTaskDelay(1), as it would affect rate of collecting data. What should I do now, to let both task run concurrently? Thanks!!
void inFromSensor(void *parameter)
{
for (;;)
{
SPI.beginTransaction(SPISettings(500000, MSBFIRST, SPI_MODE0));
// digitalWrite(SS, LOW);
SPI.write(0b000011100);
SPI.write(0b000011100);
SPI.write(0b000011100);
SPI.endTransaction();
// vTaskDelay(1000/portTICK_PERIOD_MS);
// for (int i = 0; i < 88; i++)
// {
// testBuffer1[i] = 8;
// itoa(testBuffer1[i], &buffer1[i], 10);
// }
// buffer1[0] = '1';
// buffer1[87] = '\n';
// UBaseType_t res = xRingbufferSend(buf_handle, buffer1, sizeof(buffer1), pdMS_TO_TICKS(1000));
// if (res != pdTRUE)
// {
// printf("Failed to send item\n");
// }
TIMERG0.wdt_wprotect = TIMG_WDT_WKEY_VALUE;
TIMERG0.wdt_feed = 1;
TIMERG0.wdt_wprotect = 0;
}
vTaskDelete(NULL);
}
void outToTCP(void *parameter)
{
for (;;)
{
Serial.println("a");
WiFiClient client = wifiServer.available();
if (client)
{
Serial.println("client connected");
while (client.connected())
{
unsigned long start = millis();
while (millis() - start < 5000)
{
size_t item_size;
char *item = (char *)xRingbufferReceive(buf_handle, &item_size, pdMS_TO_TICKS(1000));
if (item != NULL)
{
client.write(item);
//Return Item
vRingbufferReturnItem(buf_handle, (void *)item);
}
else
{
//Failed to receive item
printf("Failed to receive item\n");
}
}
Serial.println("done");
return;
}
client.stop();
Serial.println("Client disconnected");
}
TIMERG0.wdt_wprotect = TIMG_WDT_WKEY_VALUE;
TIMERG0.wdt_feed = 1;
TIMERG0.wdt_wprotect = 0;
}
vTaskDelete(NULL);
}
void setup()
{
Serial.begin(112500);
WiFi.begin(ssid, password);
SPI.begin(SCK, MISO, MOSI, SS);
pinMode(SS, OUTPUT);
digitalWrite(SS, HIGH);
while (WiFi.status() != WL_CONNECTED)
{
delay(1000);
Serial.println("Connecting to WiFi..");
}
wifiServer.begin();
buf_handle = xRingbufferCreate(50280, RINGBUF_TYPE_NOSPLIT);
if (buf_handle == NULL)
{
printf("Failed to create ring buffer\n");
}
Serial.println("ready");
xTaskCreatePinnedToCore(
inFromSensor, /* Task function. */
"lowPriorityTask", /* name of task. */
15000, /* Stack size of task */
NULL, /* parameter of the task */
4, /* priority of the task */
NULL, /* Task handle to keep track of created task */
1);
delay(500);
xTaskCreatePinnedToCore(
outToTCP, /* Task function. */
"highPriorityTask", /* name of task. */
15000, /* Stack size of task */
NULL, /* parameter of the task */
6, /* priority of the task */
NULL, /* Task handle to keep track of created task */
0);
delay(500);
Serial.println("ready");}
Upvotes: 1
Views: 1798
Reputation: 119
void inFromSensor(void *parameter)
{
VTaskDelay(NULL) // this will prevent task from running right after it is initialised, NULL parameter known that it is asking itself to delay.
for (;;)
{
}
}
void setup()
{
xTaskCreatePinnedToCore(inFromSensor,"lowPriorityTask", 15000, NULL,4,Task1,1);// give task handle such as Task1 and you will have to declare this on top.
delay(500);
// You can then here control the order of resuming the task
vTaskResume(Task1);// this will start the task and you should do this ideally
}
Upvotes: 0
Reputation: 21
Solved! I just switched the order of creation of task ( xTaskCreatedPinnedToCore()), create task 2 first, then task 1. Looks like in the first situation, task 1, after being created, run continuously, thus task 2 never had a chance to be created!
Upvotes: 1
Reputation: 4825
Please post the serial output.
Anyway, my guess is that Task 1 is hogging the core which runs the WiFi stack, so WiFi never gets a chance to connect. Yet Task 2 depends on WiFi to be connected. Additionally Task 2 is waiting for data to be available in the ring buffers, but your code doesn't post anything there.
Anyway, this is something that would benefit from a timer. If you need to run a sampling process at specific intervals, configure a timer with the interval, do the sampling in the interrupt and post this to your processing thread. This is much more deterministic than spinning in a loop, hogging an entire core. Plus it leaves the spare cycles to those tasks that need them (there are quite a few in addition to your code).
Upvotes: 2