hello, my program uses core 1 and core 0 of the esp32. in short, core 1 is used to handle a bluetooth connection, and has been running fine with no errors.
I have began using core 0 to run some fairly blocking code(interfaceing with tft, when the device isnt used for <30s it displays some nice images) so i put in a lot of yields() to avoid blocking some of the important system tasks core 0 runs.
everything works for a bit until the esp crashes at any random time during usage by the user, with this error:
E (190368) task_wdt: Task watchdog got triggered. The following tasks did not reset the watchdog in time:
E (190368) task_wdt: - IDLE (CPU 0)
E (190368) task_wdt: Tasks currently running:
E (190368) task_wdt: CPU 0: Task2
E (190368) task_wdt: CPU 1: loopTask
E (190368) task_wdt: Aborting.
abort() was called at PC 0x400ea01d on core 0
Backtrace:0x400830d9:0x3ffbe7dc |<-CORRUPTED
ELF file SHA256: 0000000000000000
Rebooting...
This is my code:
const int dataPin = 25; /* Q7 */
const int clockPin = 13; /* CP */
const int latchPin = 14; /* PL */
String keymap[] = {"56", "\\", "71", "esc", "70", "1", "69", "2", "68", "3", "63", "4", "62", "5", "61", "6", "60", "7", "55", "8", "54", "9", "53", "0", "52", "-", "47", "+", "46", "back", "45", "tab", "44", "q", "39", "w", "38", "e", "37", "r", "36", "t", "31", "y", "30", "u", "29", "i", "28", "o", "23", "p", "22", "[", "21", "]", "20", "enter", "15", "capslock", "14", "a", "13", "s", "12", "d", "7", "f", "6", "g", "5", "h", "4", "j", "58", "k", "59", "l", "50", ";", "57", "\'", "40", "lshift", "48", "z", "43", "x", "41", "c", "64", "v", "33", "b", "49", "n", "51", "m", "35", "<", "32", ">", "42", "/", "34", "rshift", "26", "lctrl", "25", "windows", "18", "lalt", "19", " ", "24", "options", "27", "ralt", "16", "rctrl", "17", "fn"};
TaskHandle_t Task1;
TaskHandle_t Task2;
const int bits = 72; //8x number of registers e.g 2 registers = 16
#include <BleKeyboard.h>
#define KEY_ENTER 0xE0
BleKeyboard bleKeyboard;
#include <LittleFS.h>
#define FileSys LittleFS
// Include the PNG decoder library
#include <PNGdec.h>
PNG png;
#define MAX_IMAGE_WIDTH 240 // Adjust for your images
int16_t xpos = 0;
int16_t ypos = 0;
// Include the TFT library https://github.com/Bodmer/TFT_eSPI
#include "SPI.h"
#include <TFT_eSPI.h> // Hardware-specific library
TFT_eSPI tft = TFT_eSPI(); // Invoke custom library
#define TFT_GREY 0x5AEB // New colour
#define B1 0x18E3 //button
#define B2 0x2965 //selected
#define B3 0x9CD3 //border
void setup() {
delay(5000);
Serial.begin(115200);
if (!FileSys.begin()) {
Serial.println("LittleFS initialisation failed!");
while (1) yield(); // Stay here twiddling thumbs waiting
}
bleKeyboard.begin();
tft.init();
tft.setRotation(3);
pinMode(dataPin, INPUT);
pinMode(clockPin, OUTPUT);
pinMode(latchPin, OUTPUT);
tft.fillScreen(TFT_RED);
tft.setTextColor(TFT_WHITE, TFT_RED);
tft.setCursor(30, 30);
tft.setTextFont(4);
File root = LittleFS.open("/", "r");
File file = root.openNextFile();
String strname = file.name();
strname = "/" + strname;
Serial.println(file.name());
// If it is not a directory and filename ends in .png then load it
if (!file.isDirectory() && strname.endsWith(".png")) {
// Pass support callback function names to library
int16_t rc = png.open(strname.c_str(), pngOpen, pngClose, pngRead, pngSeek, pngDraw);
if (rc == PNG_SUCCESS) {
tft.startWrite();
Serial.printf("image specs: (%d x %d), %d bpp, pixel type: %d\n", png.getWidth(), png.getHeight(), png.getBpp(), png.getPixelType());
uint32_t dt = millis();
if (png.getWidth() > MAX_IMAGE_WIDTH) {
Serial.println("Image too wide for allocated line buffer size!");
}
else {
rc = png.decode(NULL, 0);
png.close();
}
tft.endWrite();
// How long did rendering take...
Serial.print(millis() - dt); Serial.println("ms");
}
}
xTaskCreatePinnedToCore(
Task1code, /* Task function. */
"Task1", /* name of task. */
10000, /* Stack size of task */
NULL, /* parameter of the task */
1, /* priority of the task */
&Task1, /* Task handle to keep track of created task */
1); /* pin task to core 0 */
delay(500);
xTaskCreatePinnedToCore(
Task2code, /* Task function. */
"Task2", /* name of task. */
10000, /* Stack size of task */
NULL, /* parameter of the task */
tskIDLE_PRIORITY, /* priority of the task */
&Task2, /* Task handle to keep track of created task */
0); /* pin task to core 1 */
delay(500);
}
String ios = ""; //in my case, strings fit better. recommend using array
String ios2 = "";
bool capslock = false;
bool menuopen = false;
int key = 0;
unsigned long idlestamp = millis();
void Task1code( void * pvParameters ) {
// Step 1: Sample
for (;;) {
digitalWrite(latchPin, LOW);
digitalWrite(latchPin, HIGH);
// Step 2: Shift
ios = "";
for (int i = 0; i < bits; i++) {
int bit = digitalRead(dataPin);
if (bit == HIGH) {
ios.concat("1");
} else {
ios.concat("0");
}
digitalWrite(clockPin, HIGH); // Shift out the next bit
digitalWrite(clockPin, LOW);
}
for (int b = 0; b < ios.length(); b++) {
if (ios[b] != ios2[b]) {
if (ios[b] == '0') {
Serial.println(b);
key = b;
for (int h = 0; h < 120; h = h + 2) {
if (keymap[h] == String(b)) {
String letter = keymap[h + 1];
if (letter == "esc") {
bleKeyboard.press(KEY_ESC);
}
else if (letter == "back") {
bleKeyboard.press(KEY_BACKSPACE);
}
else if (letter == "tab") {
bleKeyboard.press(KEY_TAB);
}
else if (letter == "enter") {
bleKeyboard.press(KEY_ENTER);
}
else if (letter == "lshift") {
bleKeyboard.press(KEY_LEFT_SHIFT);
}
else if (letter == "rshift") {
bleKeyboard.press(KEY_RIGHT_SHIFT);
}
else if (letter == "lctrl") {
bleKeyboard.press(KEY_LEFT_CTRL);
}
else if (letter == "rctrl") {
bleKeyboard.press(KEY_RIGHT_CTRL);
}
else if (letter == "lalt") {
bleKeyboard.press(KEY_LEFT_ALT);
}
else if (letter == "ralt") {
bleKeyboard.press(KEY_RIGHT_ALT);
}
else if (letter == "windows") {
bleKeyboard.press(KEY_LEFT_GUI);
}
else if (letter == "windows") {
bleKeyboard.press(KEY_LEFT_GUI);
}
else if (letter == "options") {
idlestamp = millis();
menuopen = true;
}
else if (letter == "capslock") {
if (capslock == false) {
capslock = true;
}
else {
capslock = false;
}
}
else {
if (capslock == true) {
letter.toUpperCase();
bleKeyboard.press(letter[0]);
}
else {
bleKeyboard.press(letter[0]);
}
}
}
}
}
else if (ios[b] == '1') {
for (int h = 0; h < 120; h = h + 2) {
if (keymap[h] == String(b)) {
String letter = keymap[h + 1];
if (letter == "esc") {
bleKeyboard.release(KEY_ESC);
}
else if (letter == "back") {
bleKeyboard.release(KEY_BACKSPACE);
}
else if (letter == "tab") {
bleKeyboard.release(KEY_TAB);
}
else if (letter == "enter") {
bleKeyboard.release(KEY_ENTER);
}
else if (letter == "lshift") {
bleKeyboard.release(KEY_LEFT_SHIFT);
}
else if (letter == "rshift") {
bleKeyboard.release(KEY_RIGHT_SHIFT);
}
else if (letter == "lctrl") {
bleKeyboard.release(KEY_LEFT_CTRL);
}
else if (letter == "rctrl") {
bleKeyboard.release(KEY_RIGHT_CTRL);
}
else if (letter == "lalt") {
bleKeyboard.release(KEY_LEFT_ALT);
}
else if (letter == "ralt") {
bleKeyboard.release(KEY_RIGHT_ALT);
}
else if (letter == "windows") {
bleKeyboard.release(KEY_LEFT_GUI);
}
else if (letter == "windows") {
bleKeyboard.release(KEY_LEFT_GUI);
}
else {
if (capslock == true) {
letter.toUpperCase();
bleKeyboard.release(letter[0]);
}
else {
letter.toLowerCase();
bleKeyboard.release(letter[0]);
}
}
}
}
}
delay(70);//debounce
}
}
ios2 = ios;
}
}
const long interval = 50000;
int latch1 = 1;
int currentbutton = 1;
int screen = 1;
void os() {
}
void Task2code(void* arg) {
for (;;) {
if (millis() - idlestamp > interval) {
Serial.println("idling");
latch1 = 1;
menuopen = false;
}
while (millis() - idlestamp > interval) {
backdrop();
}
if (menuopen == true) {
if (latch1 == 1) {
tft.fillScreen(TFT_BLACK);
latch1 = 0;
}
if (key == 8) {
yield();
Serial.println("cb:" + String(currentbutton));
currentbutton = currentbutton + 1;
if (currentbutton > 4) {
currentbutton = 1;
}
if (screen == 1) {
vTaskDelay(1);
yield();
tft.setTextColor(TFT_WHITE);
if (currentbutton == 1) {
tft.fillSmoothRoundRect(10, 20, 220, 30, 15, B2, TFT_BLACK);
tft.fillRect(10, 35, 220, 35, B2);
}
else {
tft.fillSmoothRoundRect(10, 20, 220, 30, 15, B1, TFT_BLACK);
tft.fillRect(10, 35, 220, 35, B1);
}
tft.drawCentreString("macro's", 120, 28, 4);
if (currentbutton == 2) {
tft.fillRect(10, 70, 220, 50, B2);
}
else {
tft.fillRect(10, 70, 220, 50, B1);
}
tft.drawCentreString("binds", 120, 82, 4);
if (currentbutton == 3) {
tft.fillRect(10, 120, 220, 50, B2);
}
else {
tft.fillRect(10, 120, 220, 50, B1);
}
tft.drawCentreString("wallpaper", 120, 132, 4);
if (currentbutton == 4) {
tft.fillRect(10, 170, 220, 35, B2);
tft.fillSmoothRoundRect(10, 190, 220, 30, 15, B2, TFT_BLACK);
}
else {
tft.fillRect(10, 170, 220, 35, B1);
tft.fillSmoothRoundRect(10, 190, 220, 30, 15, B1, TFT_BLACK);
}
tft.drawCentreString("settings", 120, 182, 4);
yield();
key = 0;
}
}
}
yield();
}
}
void loop() {
}
void backdrop() {
File root = LittleFS.open("/", "r");
while (File file = root.openNextFile()) {
String strname = file.name();
strname = "/" + strname;
Serial.println(file.name());
// If it is not a directory and filename ends in .png then load it
if (!file.isDirectory() && strname.endsWith(".png")) {
// Pass support callback function names to library
int16_t rc = png.open(strname.c_str(), pngOpen, pngClose, pngRead, pngSeek, pngDraw);
if (rc == PNG_SUCCESS) {
tft.startWrite();
Serial.printf("image specs: (%d x %d), %d bpp, pixel type: %d\n", png.getWidth(), png.getHeight(), png.getBpp(), png.getPixelType());
uint32_t dt = millis();
if (png.getWidth() > MAX_IMAGE_WIDTH) {
Serial.println("Image too wide for allocated line buffer size!");
}
else {
rc = png.decode(NULL, 0);
png.close();
}
tft.endWrite();
// How long did rendering take...
Serial.print(millis() - dt); Serial.println("ms");
}
}
int p = 0;
while (p < 35000 && millis() - idlestamp > interval) {
delay(1);
p = p + 1;
yield();
}
}
}
void pngDraw(PNGDRAW *pDraw) {
uint16_t lineBuffer[MAX_IMAGE_WIDTH];
png.getLineAsRGB565(pDraw, lineBuffer, PNG_RGB565_BIG_ENDIAN, 0xffffffff);
tft.pushImage(xpos, ypos + pDraw->y, pDraw->iWidth, 1, lineBuffer);
}