Исправление ошибок перезаписи памяти, вероятно, из-за malloc на STM32 Nucleo-F334R8 - PullRequest
0 голосов
/ 27 апреля 2019

Я надеюсь, что это четкое объяснение моей проблемы. Я чуть более недели бегал по разным учебникам, сейчас пытаюсь решить эту проблему:

Недавно я занимался редизайном дизайна программного обеспечения для класса.проект после обратной связи и тестирования на STM32 Nucleo-F334R8 (мой исходный код был пронизан ошибками памяти и синхронизации)

В настоящее время я сталкиваюсь с двумя основными ошибками:

(Эта проблема была решена)

Я использовал sprintf без учета записи завершающего нулевого символа вне выделенной памяти.

При обработке данных USART с использованиемUSART 1 в асинхронном режиме со скоростью 115200 бод:

Запрограммируйте полученный сигнал SIGTRAP, Trap / breakpoint trap.0x08002c08 в memset ()

Запрограммировать полученный сигнал SIGTRAP, Trap / breakpoint trap.0x08002c08 в memset ()

Запрограммировать полученный сигнал SIGTRAP, Trap / breakpoint trap.0x08002c08 в memset ()

Запрограммировать полученный сигнал SIGTRAP, Trap / breakpoint trap.0x08002c08 в memset ()

Запрограммировать полученный сигнал SIGTRAP, Trap / breakpoint trap.0x080056b4 в std.isra ()

Значение, хранящееся по адресу 0x08002c08, о котором идет речь, обычно очень большое, обычно что-то вроде 134228385 в десятичном виде.Также, если я решительно пошагово рассмотрю проблему, программа продолжит нормально работать, и никогда не встретится с проблемой снова , что я нахожу странной возможной причиной?

ОБНОВЛЕНИЕ: Итак, я проследил проблему memset вокругнемного и обнаружил, что это происходит во время моего setOutputBuffer метода:

String>,%5d,%8s,%3d,%3d,%3d,%4d,%4d,%4d,%10.6f,%11.6f,%7.1f,%3d,%3.1f\n",uptime,timeString,temperature,pressure,humidity,acc1,acc2,acc3,latitude,longitude,altitude,current,voltage);
} ``` Which leads me to believe the issue lies in finding a value that
is being used to set the Output buffer message.

I would like advice on how to further troubleshoot these two issues
and whether there is a chance that the memset error is related the
later bss error.

My String Tokenizing code(edited):

```c void tokenize(char* in){     const char *p = in;     const char 
delim[] = ",";    char *token = NULL;     uint8_t n = 0;

  do{

      size_t length = strcspn(p, delim);      if(length > 0){             if(token ==
NULL){
              token = malloc(sizeof(char)*length); // create memory space for the token
              memset(token, 0, length); // ensure initialized memory is blank
              sprintf(token, "%.*s",(int)length,p); // store the token from a substring of Input Buffer
              p+=length; // move pointer to next ','
              parseToken(token, n); // extract information from the token be it latitude, longitude etc
              memset(token, 0, length); // clear the token
              free(token); // free up the token's spot in memory
              token = NULL; // set token pointer to null
              n++;            }

      }


  }while(*((++p)+1) != '*'); // The expected string ends with a
checksum character '*' after the last ',' } ``` I've re-examined the
function and made a lot of changes now I can successfully step through
the entire function without issue, the program then returns to my main
loop, and I let it run for a while but then I suddenly run back into
the same memset issue, even without receiving any bytes over USART
here is the code for my main loop and the subsequent function calls it
makes:

```c

  while (1)   {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */

      if (byteFlag){          byteRecieved();             byteFlag = 0;       }

      if(msgFlag){            msgRecieved();          msgFlag = 0;        }

      if(secFlag){            setOutputBuffer();          HAL_UART_Transmit(&huart1,
(uint8_t *)bufferOut, 91, 1000);          secFlag = 0;        }

  } ``` byteReceived: ```c if((char) byteIn == '$'){
      clearInputBuffer();     } else if((char) byteIn == '\n'){

      msgFlag = 1;    }

  else{       storeChar();    } ```

msgReceived: ```c if(isValid()){      if (checksum()) {
          tokenize(bufferIn);             clearInputBuffer();         }   } ```

isValid: ```c char substr[5];     strncpy(substr, (bufferIn+1), 5);
  if(!strcmp(substr, "GPGGA")){       return 1;   }

  return 0; ```

checksum: ```c int checksum(){    int calc_checksum = 0;  int
in_checksum;  int i = 0;  char checkstr[2];   uint8_t hasCheckSum = 0;

  for(int j = 0; j<91; j++){      if (bufferIn[j] == '*') {           hasCheckSum
= 1;          i = 1;      }   }

  if (hasCheckSum) {      while (bufferIn[i] != '*'){             calc_checksum ^=
bufferIn[i];          i++;        }       checkstr[0] = bufferIn[i+1];        checkstr[1]
= bufferIn[i+2];  } else {return 0;}



  in_checksum = parseStr_HexToInt(checkstr);

  if (calc_checksum == in_checksum){      return 1;   } else {        return 0;
  } } ```

clearInputBuffer: ```c void clearInputBuffer(){   int i = 0;

  for(i = 0; i < 100; i++){       bufferIn[i] = ' ';  }   bufferIn[0] = '$';
} ```

(Эта проблема была решена)

По существу источник моегопроблема заключалась в неправильном использовании sprintf и перезаписи программного кода нулевыми символами

Я обнаружил ловушку точки останова при заполнении сегмента bss памяти платы

И после добавления семи портов GPIO дляЖК-дисплей в 4-битном режиме (а именно PA12, PA11, PB12, PB11, PB2, PB1, PB15) и два для двухканального АЦП в режиме DMA (PA1, PA0):

Запрограммируйте принятый сигнал SIGTRAP,Трассировка / Точка останова.LoopFillZerobss () at .. \ startup / startup_stm32f334x8.s: 103 103 cmp r2, r3 При попытке реализовать функции LCD и ADC я получаю сообщение об ошибке прерывания точки останова во время запуска функции LoopFillZerobss, которая оказалась фатальной , особенноотключив мой USART от отчетов вообще (однако он все еще может получать байты в качестве прерываний и обрабатывать токены и т. д., просто отказывается передавать), прочитав сегмент bss, я попытался решить проблему, инициализировав какМногие глобальные переменные, как я мог бы к ненулевым значениям, это не сработало, проблема наблюдается после добавления настроек STM32CubeMx для АЦП и 7 выводов GPIO, используемых на ЖК-дисплее, однако ни одна из них не использует, насколько мне известно, унифицированные переменные, если толькопредопределенный код, сгенерированный CubeMX, выходит за пределы сегмента памяти bss и что размер сегмента bss слишком велик для памяти платы (что, я подозреваю, маловероятно, но не исключает).

ЭссенИдея этого проекта заключается в том, чтобы получать различные данные через USART, ADC и более поздние I2C и отображать различные аспекты данных через USART и LCD в настоящее время, если я отбрасываю ошибки ADC и LCD, мой код USART функционирует, так как ошибка memset ()не смертельно, но я подозреваю, что выход из него вызывает у меня только более поздние проблемы, но я также не уверен, где исправить мой код токенизации, предполагая, что это корень моих проблем.

1 Ответ

0 голосов
/ 27 апреля 2019

По сути, источником моей проблемы было неправильное использование sprintf и перезапись программного кода нулевыми символами

Обеспечивая использование snprintf вместо sprintf со строками четко определенного размера, я больше не сталкивался с проблемами памяти.

...