Перезагрузка ESP32 при преобразовании строки в шестнадцатеричный массив

esp32 error

Я написал этот код для преобразования строки в шестнадцатеричный массив.

const char* hexstring = "0x21 0x73 0x10 0xfa 0x7a 0x00 0xff .../*40995 character long string*/....0xaa"    
void setup() {
    char* temp;
    //Serial.printf("%s",hexstring);
    unsigned int number[8199];
    
    number[0] = strtoul (hexstring,&temp,16);
    for(int i=1;i<8199;i++)
     number[i]= (int)strtoul(temp, &temp, 16);
    
    for(int i=0;i<8199;i++)
        {
            if(i%64)
                printf("\n");
            printf("%d, ",number[i]);
        }
}

void loop(){
}

Но это вызывает перезагрузку ESP32.

Может ли кто-нибудь помочь мне с причиной?

, 👍-1

Обсуждение

Я не совсем понимаю, что вы пытаетесь сделать со своим кодом. Это не имеет большого смысла для меня. Во-первых: почему вы предоставляете &temp для strtoul()? temp — неинициализированный указатель, @chrisl

Почему вы пишете number[0] два раза вместо того, чтобы использовать number[i]? Почему этот цикл for имеет длину всего 5 итераций, а другой, который не записывает число, имеет длину 8199 итераций? В общем, я не знаю, как помочь здесь, кроме как указать на эти вещи. Может быть, опишите, что вы пытаетесь сделать, @chrisl

@chrisl Я исправил это, это должно было быть «число [i]», немного поискав, я нашел способ преобразовать строку шестнадцатеричных значений в массив шестнадцатеричных значений. Итак, я попробовал это в онлайн-компиляторе C, он отлично работает. Например, const char* hexstring = "0x21 0x49..." становится unsigned int number[8199]=[33, 73...`, @Just doin Gods work

Плохо, я отредактировал код, чтобы попробовать более короткую строку, и по ошибке скопировал ее. Я исправил это сейчас. Итерация 8199, @Just doin Gods work

Тем не менее, почему вы используете temp неинициализированным? В этой позиции параметр является конечным указателем (указатель на то место, где должно остановиться преобразование). Нулевой указатель здесь означает преобразование до конца строки. Так что это сводится к тому, что temp неявно инициализируется нулевым указателем. Возможно, это относится к вашему онлайн-компилятору. Пожалуйста, попробуйте использовать NULL вместо temp или strtoul(), @chrisl

@chrisl, _ «где преобразование должно остановиться» _ на самом деле используется как _output_ not input. Он не говорит strtoul, где остановить лексирование, он дает strtoul средство сообщить вызывающей стороне, где он остановился. Таким образом, вы можете использовать его, чтобы выяснить, где возобновить следующую операцию, что они и делают. Если вы дадите ему NULL, вы просто скажете: «Мне все равно, где» вы остановились. Если вы дадите ему указатель на указатель символа, вы скажете: «Мне все равно, где вы остановились, скажите мне этим указателем, на что я вам указываю»., @timemage

@timemage А, ладно, значит, я неправильно понял, @chrisl


1 ответ


Лучший ответ:

0
void setup() {
    char* temp;
    //Serial.printf("%s",hexstring);
    unsigned int number[8199]; <----- too much.

Итак, вы пытаетесь поместить в стек объект размером 32796 байт. Я точно не знаю, почему вы видите то проявление, которым вы являетесь, но я не удивлен.

Я просто взял ESP32-CAM и начал играть с разными размерами и обнаружил, что около 1800 (unsigned ints) — это то место, где все начинает идти не так, как надо, иногда, а не постоянно. По подсчету 2000 он постоянно перезагружается с rst:0xc (SW_CPU_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT) с переходом на rst:0x10 (RTCWDT_RTC_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT) и позже примерно до 5000 становится rst:0x8 (TG1WDT_SYS_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)

Я могу заполнить некоторые детали позже, если я изучу их глубже. ESP32 и SDK достаточно сложны, поэтому вполне может существовать функция, которая позволит использовать более высокий уровень стека. Но это в основном для удовлетворения любопытства.

Обычно не помещают в стек очень большие объекты (относительно размера системы). Я не решаюсь сказать вам, что именно вы должны делать; меня не удивит, если вам вообще не нужен этот массив для того, что вы в конечном итоге хотите сделать, но это другой вопрос). Итак, я просто скажу, что извлеките его из стека с помощью динамического выделения памяти (например, с помощью new или malloc), возможно, используя интеллектуальный указатель (например, std ::unique_ptr), чтобы управлять этим, поскольку они доступны в ESP32, или, возможно, просто сделать переменную static локальной или глобальной. Или еще раз, если возможно, выяснить, почему вам может не понадобиться этот массив.

Простое минимальное изменение

Итак, я не собираюсь говорить вам, что это хорошая идея, но минимальное изменение будет состоять в том, чтобы static квалифицировать это как static unsigned int number[8199]; Тогда вы не получите эту причину сброса здесь, по этой причине.


Некоторые подробности для тех, кому интересно

Если вы хотите увидеть некоторые внутренности, посмотрите на ядро ESP32 для Arduino, где оно создает задачу, которая в конечном итоге запускает setup() для вас. Вы можете видеть, что он вызывает getArduinoLoopTaskStackSize() возвращает ARDUINO_LOOP_STACK_SIZE, который по умолчанию равен 8192. 8192 байта, а не unsigned int. Поскольку sizeof(unsigned int) равен 4, это очень приблизительно находится в районе 1800 unsigned int, когда все начало разваливаться в мое тестирование выше. Вместо того, чтобы копаться в конфигурации, я просто сделал скетч, который выполняет Serial.println(getArduinoLoopTaskStackSize()); и да, он печатает 8192.

getArduinoLoopTaskStackSize – это слабо определенная функция, которая позволяет переопределять что-то в другом месте программа для перегрузки стандартной. Итак, просто из любопытства я написал следующее:

size_t getArduinoLoopTaskStackSize(void) {
  size_t r_size = sizeof(unsigned int [8199]); // точно такой же размер вашего массива
  r_size += r_size >> 3; // добавить около 1/8 (или 12,5%) дополнительно
  return r_size;
}

Он больше не вылетает. Должны ли вы это сделать? Возможно нет. Но если у вас когда-нибудь появится веская причина поместить массив 32 КБ в стек на ESP32, это может быть вариантом. Я в основном просто сделал это, чтобы посмотреть, что произойдет. Его почти не тестировали.

,