Qoʻllanma · FreeRTOS · Ikki yadro
FreeRTOS bilan ishni ESP32 ning ikkinchi yadrosiga qoʻying
Klassik ESP32 da ikki yadro bor, lekin Arduino loop() hamisha faqat bittasida
aylanadi. loop() ga sekin datchik oʻqishi yoki maʼlumot tahlili tushishi bilanoq veb-sahifa
sekinlashadi, Wi-Fi esa hiqillaydi. Yechim allaqachon chipda: FreeRTOS. Vazifa yarating,
uni boshqa yadroga biriktiring — va ular yonma-yon ketadi.
Bu millis() va uzilishlardan keyingi qadam: ular bitta siklni bloklanishдан saqlaydi; FreeRTOS esa bir nechta siklni bir vaqtda — haqiqiy apparat yadrolarida yuritishга imkon beradi.
Siz allaqachon undan foydalanyapsiz
ESP32 Arduino yadrosi FreeRTOS ustida ishlaydi. Sizning setup()/loop() — oʻzi
bir vazifa (loopTask), 1-yadroga biriktirilgan. Wi-Fi/Bluetooth steki oʻz
vazifalarini, asosan 0-yadroda yuritadi. Demak «vazifa qoʻshish» ekzotika emas — siz tizim
allaqachon qilayotgan narsadan yana bittasini yaratasiz.
Oʻz vazifangiz
Vazifa — bu hech qachon qaytmaydigan cheksiz for(;;) siklli funksiya. Uni bir marta
yaratasiz, planировщик esa uni abadiy yuritib, protsessor vaqtini u bilan qolgani orasида boʻlib beradi.
Hamma qoqiladigan qoida: vazifa ichida delay() emas, vTaskDelay() ishlating —
vTaskDelay kutayotganда protsessorni boshqa vazifalarга qaytaradi.
Ikkinchi yadroga biriktiring
xTaskCreatePinnedToCore() ni ishlating va unga 0-yadroni bering — shunda
ogʻir ish 1-yadrodan chiqib ketadi, u yerда loop() va veb-server yashaydi:
void sensorTask(void *pv) {
for (;;) {
float t = readTemp(); // your slow work
Serial.printf("temp: %.1f\n", t);
vTaskDelay(pdMS_TO_TICKS(1000)); // yield — never delay() in a task
}
}
void setup() {
Serial.begin(115200);
xTaskCreatePinnedToCore(
sensorTask, // function to run
"sensor", // name (for debugging)
4096, // stack in bytes — too small = crash/reboot
NULL, // parameter
1, // priority (higher = more urgent)
NULL, // task handle (optional)
0); // core 0 — leave core 1 for loop() + Wi-Fi
}
void loop() {
// core 1: keep the web server / UI / Wi-Fi responsive
} Yetti argument: funksiya, nom, stek hajmi, parametr, ustuvorlik, ixtiyoriy dastak va yadro (0 yoki 1). Ulardan ikkitasi yangilarni tishlaydi: stek juda kichik boʻlsa — vazifa xotiraга tegishi bilan qulaydi; ustuvorlik esa nisbiy — boshqaruvni bermaydigan yuqori ustuvorlikli vazifa pastdagi hammasini ochlikка mahkum qiladi.
Yadrolar orasида maʼlumot uzatish — navbat
Endi tuzoq — umumiy maʼlumot. 0-yadroda yozilib, 1-yadroda oʻqilgan oddiy global «yirtilishi» yoki eski
holatда oʻqilishi mumkin — bitta tekislangan soʻzdan kattaroq narsa uchun bitta volatile
yetmaydi. Toza yoʻl — navbat: bir vazifa qiymatlarни qoʻyadi, ikkinchisi oladi, qulflashни
FreeRTOS oʻz zimmasига oladi:
QueueHandle_t q;
void producer(void *pv) {
for (;;) {
float v = readTemp();
xQueueSend(q, &v, 0); // hand the value across — no shared globals
vTaskDelay(pdMS_TO_TICKS(1000));
}
}
void setup() {
q = xQueueCreate(8, sizeof(float)); // room for 8 floats
xTaskCreatePinnedToCore(producer, "prod", 4096, NULL, 1, NULL, 0);
}
void loop() {
float v;
while (xQueueReceive(q, &v, 0) == pdTRUE) // core 1 drains it safely
Serial.println(v);
} Navbatlar «ishlab chiqaruvchi/isteʼmolchi» sxemasi uchun ideal — datchik-vazifa oʻlchaydi, UI-vazifa
koʻrsatadi. Ikkala tomondan tegadigan umumiy struktura uchun uni myuteks bilan
himoya qiling (xSemaphoreCreateMutex()). Qoida: nusxalarни navbat orqali uzating,
globallarни boʻlishmang.
Platani qayta yuklaydigan tuzoqlar
- Stek juda kichik. 1–2 KB miltillovchi uchun yetadi; Wi-Fi, JSON yoki
Stringga tegadigan har narsa 4–8 KB xohlaydi. Stek toshib ketishi darhol qayta yuklaydi. - Vazifa ichидаги
delay()oʻsha yadro planировщик slotини bloklaydi —vTaskDelay(pdMS_TO_TICKS(ms))ishlating. - 0-yadro watchdogi. Boshqaruvni bermaydigan ochkoʻz 0-yadro vazifasi task-watchdogни
panikaga soladi. Har siklда hech boʻlmaganда bir marta
vTaskDelay()qiling. - Ikki vazifадан
Serialaralashib ketishi mumkin; normal log uchun chop etishни bitta vazifa orqali yoʻnaltiring (yana navbat). - Ustuvorliklar nisbiy. Hammasini yuqori qilmang — koʻp vazifани 1 dan boshlang.
⚠ Qaysi ESP’lar haqiqatan ikki yadroli
- Ikki yadro: klassik ESP32 va ESP32-S3. Bu yerда 0-yadroga biriktirish haqiqiy parallelizm beradi.
- Bitta yadro: ESP32-C3, C6, S2, H2. FreeRTOS vazifalari baribir
ishlaydi — planировщик ularга vaqt boʻlib beradi — lekin biriktirish uchun ikkinchi yadro yoʻq.
xTaskCreatePinnedToCore(…, 1)shunchaki 0-yadroда bajariladi. Struktura uchun zoʻr, yukни boʻlish uchun emas. - FreeRTOS’siz (Arduino yadrosi): ESP8266 bitta kooperativ sikl
yuritadi.
xTaskCreateyoʻq — millis() va uzilishlarга tayaning. Nima borligini bilmaysizmi? Chiplar qoʻllanmasini koʻring.
Deyarli har loyihада oʻzini oqlaydigan usul: loop() ni tarmoq va UI uchun qoldiring,
bloklovchi ishни — datchik, fayl, tahlil — navbat orqali javob qaytaradigan biriktirilgan vazifага
koʻchiring. Plata duduqlanishни toʻxtatadi, dashboard esa datchiklar oʻz ishini qilayotganда silliq qoladi.
Platangizда ikkinchi yadro bor-yoʻqligini — yoki datchik-vazifa uchun qaysi pinlar boʻshligini bilmaysizmi?