#c #freertos #lpc
#c #freertos #lpc
Вопрос:
Приведенная ниже функция выполняется в LPC1769. Я использую FreeRTOS версии 10. У меня есть HardFault
. Я отладил, и я думаю, что загнал проблему в угол после долгих часов.
Если я запускаю эту функцию, она выдает HardFault
. Изначально я подозревал malloc
substr3
, что это вызвано функцией. Освобождение выделенной памяти не помогло. Поэтому я начал комментировать код блок за блоком, пока не найду более точное местоположение проблемы в parseMessage
функции.
Если я закомментирую строки между /* START OF PROBLEMATIC AREA */
и /* END OF PROBLEMATIC AREA */
остальной код работает без единого сбоя.
Все, что я делаю в этом блоке кода, я присваиваю значения структурным переменным. Структура является глобальной и инициализирована. Я считаю, что эти строки в конечном итоге вызывают проблему. Может быть, косвенно, я пока не знаю.
например strcpy(productInfoLeft.ucActualID, pid);
Если я запускаю все коды в parseMessage
, это работает для одного или нескольких сообщений, они анализируются нормально, а затем MCU перестает отвечать.
Структура в файле с именем common.h
struct ProductInfoLeft
{
char ucActualID[ 7 ];
char ucProductName[ 13 ];
char ucBestBeforeDate[ 13 ];
char ucPrinted[ 4 ];
char ucToBePrinted[ 4 ];
char ucLane[ 3 ];
char ucLcdNumber [ 2 ];
char ucPrinterLane [ 3 ];
char ucSupplierInfo [ 13 ];
};
extern struct ProductInfoLeft productInfoLeft;
struct ProductInfoRight
{
char ucActualID[ 7 ];
char ucProductName[ 13 ];
char ucBestBeforeDate[ 13 ];
char ucPrinted[ 4 ];
char ucToBePrinted[ 4 ];
char ucLane[ 3 ];
char ucLcdNumber [ 2 ];
char ucPrinterLane [ 3 ];
char ucSupplierInfo [ 13 ];
};
extern struct ProductInfoRight productInfoRight;
Инициализация структуры происходит в файле с именем lcdtasks.c
;
struct ProductInfoLeft productInfoLeft = {
.ucActualID = "",
.ucProductName = "",
.ucBestBeforeDate = "",
.ucPrinted = "",
.ucToBePrinted = "",
.ucLane = "",
.ucLcdNumber = "",
.ucPrinterLane = "",
.ucSupplierInfo = ""
};
struct ProductInfoRight productInfoRight = {
.ucActualID = "",
.ucProductName = "",
.ucBestBeforeDate = "",
.ucPrinted = "",
.ucToBePrinted = "",
.ucLane = "",
.ucLcdNumber = "",
.ucPrinterLane = "",
.ucSupplierInfo = ""
};
И функция синтаксического анализатора в другом файле вызывается uarttask.c
;
void parseMessage(char * message){
//Sample data
//const char* str = "7E00002A347C31323030302D3132353330387C33302E30372E323032307C31317C33307C33317C31352D31367C31357C317C57656E67657274880D0000";
// Parsing the frame
char* start;
char* len;
char* cmd;
char* data;
char* chksum;
char* end;
stripEOL(message);
unsigned int messagelen = strlen(message);
start = substr3(message, 0, 2);
len = substr3(message, 2, 4);
cmd = substr3(message, 6, 2);
data = substr3(message, 8, messagelen-8-4);
chksum = substr3(message, messagelen-4, 2);
end = substr3(message, messagelen-2, 2);
// Converting hex (only for data) to string
char str[250];
hex_to_string(data, str, sizeof(str));
// Parsing the data in variables
//Sample data content to be parsed in variables;
//char str1[50] ="7|10000-145310|12.10.2018|1|10|0|15-16|15|1|Wegert";
char pid[6], pname[12], bbdate[10], pnr[2], ltoprinted[3], lprinted[3], planes[5], laneNr[2], lcdNr[1], sinfo[12];
strcpy(pid, strtok(str , "|"));
strcpy(pname, strtok(NULL , "|"));
strcpy(bbdate, strtok(NULL, "|"));
strcpy(pnr , strtok(NULL, "|"));
strcpy(ltoprinted , strtok(NULL, "|"));
strcpy(lprinted, strtok(NULL, "|"));
strcpy(planes, strtok(NULL, "|"));
strcpy(laneNr, strtok(NULL, "|"));
strcpy(lcdNr, strtok(NULL, "|"));
strcpy(sinfo, strtok(NULL, "|"));
uint8_t resultLCDNr1 = strncmp(lcdNr, "1", 1);
uint8_t resultLCDNr2 = strncmp(lcdNr, "2", 1);
uint8_t result7E = strcmp(start, pcStart);
uint8_t result0D = strcmp(end, pcEnd);
uint8_t result2A = strcmp(cmd, pcProductChange);
uint8_t result30 = strcmp(cmd, pcSupplierChange);
char planeleft[2], planeright[2], tempplanes[5];
strcpy(tempplanes, planes); // If this is used, the next strcpy causes lprinted variable's first element to be "0"
strcpy(planeleft, strtok(tempplanes , "-"));
strcpy(planeright, strtok(NULL , "-"));
/* START OF PROBLEMATIC AREA */
if (result7E == 0 amp;amp; result0D == 0){
if (result2A == 0){ //Product Change
if (resultLCDNr1 == 0){
strcpy(productInfoLeft.ucActualID, pid);
strcpy(productInfoLeft.ucPrinterLane, planeleft);
strcpy(productInfoLeft.ucProductName, pname);
strcpy(productInfoLeft.ucBestBeforeDate, bbdate);
strcpy(productInfoLeft.ucPrinted, lprinted);
strcpy(productInfoLeft.ucToBePrinted, ltoprinted);
strcpy(productInfoLeft.ucLane, laneNr);
strcpy(productInfoLeft.ucLcdNumber, lcdNr);
strcpy(productInfoLeft.ucSupplierInfo, sinfo);
}else if (resultLCDNr2 == 0){
strcpy(productInfoRight.ucActualID, pid);
strcpy(productInfoRight.ucPrinterLane, planeright);
strcpy(productInfoRight.ucProductName, pname);
strcpy(productInfoRight.ucBestBeforeDate, bbdate);
strcpy(productInfoRight.ucPrinted, lprinted);
strcpy(productInfoRight.ucToBePrinted, ltoprinted);
strcpy(productInfoRight.ucLane, laneNr);
strcpy(productInfoRight.ucLcdNumber, lcdNr);
strcpy(productInfoRight.ucSupplierInfo, sinfo);
}else{
return;
}
SetProductChangeOnLCD(lcdNr);
}
if (result30 == 0){ //Supply Change
if (resultLCDNr1 == 0){
strcpy(productInfoLeft.ucActualID, pid);
strcpy(productInfoLeft.ucPrinterLane, planeleft);
strcpy(productInfoLeft.ucProductName, pname);
strcpy(productInfoLeft.ucBestBeforeDate, bbdate);
strcpy(productInfoLeft.ucPrinted, lprinted);
strcpy(productInfoLeft.ucToBePrinted, ltoprinted);
strcpy(productInfoLeft.ucLane, laneNr);
strcpy(productInfoLeft.ucLcdNumber, lcdNr);
strcpy(productInfoLeft.ucSupplierInfo, sinfo);
}else if (resultLCDNr2 == 0){
strcpy(productInfoRight.ucActualID, pid);
strcpy(productInfoRight.ucPrinterLane, planeright);
strcpy(productInfoRight.ucProductName, pname);
strcpy(productInfoRight.ucBestBeforeDate, bbdate);
strcpy(productInfoRight.ucPrinted, lprinted);
strcpy(productInfoRight.ucToBePrinted, ltoprinted);
strcpy(productInfoRight.ucLane, laneNr);
strcpy(productInfoRight.ucLcdNumber, lcdNr);
strcpy(productInfoRight.ucSupplierInfo, sinfo);
}else{
return;
}
SetSupplierChangeOnLCD(lcdNr);
}
}
/* END OF PROBLEMATIC AREA */
free(start);
free(len);
free(cmd);
free(data);
free(chksum);
free(end);
}
Функция подстроки:
char *substr3(char const *input, size_t start, size_t len) {
char *ret = malloc(len 1);
memcpy(ret, input start, len);
ret[len] = '';
return ret;
}
Комментарии:
1. И как выглядят данные? NTW: покажите нам функцию substr(), тоже, пожалуйста.
2. Нет
sizeof
. Вам нужно использоватьstrlen
. И настоятельно рекомендовал бы не сохранять текущий код как есть. Он полон уязвимостей, использующих переполнение буфера. Подача неожиданных входных данных приведет к пробоинам по всей памяти.3. @user3121023, потому что мне нужно оставить еще одно место для
?
4. @user3121023, действительно, их больше. Но это просто неправильный образец. Это правильный;
char str1[50] ="7|10000-145310|12.10.2018|1|10|0|15-16|15|1|Wegert";
5. @Sener В вашей строке примера 2-й токен
10000-145310
содержит 12 символов. Подсчет нулевого терминатораstrcpy(pname, strtok(NULL , "|"));
приведет к переполнению выделенногоchar pname[12];
.
Ответ №1:
Просто для дальнейшего использования, я хотел бы поделиться своими выводами и решением проблем.
Было две проблемы. Одним из них были размеры массива с символом, используемым для strcpy. Не были установлены должным образом, как упоминали некоторые участники.
Как только эти размеры массива были исправлены, другая проблема проявилась более четко. Речь шла о malloc. По какой-то причине, хотя некоторые замечания говорят об обратном в различных ресурсах, если вы используете malloc в реализации FreeRTOS, есть вероятность, что у вас может быть HardFault. Как только я переключился на FreeRTOS, предложив функции malloc и free, все выровнялось. Проблема с HardFault волшебным образом исчезла.
Я только что разместил эти две функции-оболочки (где-то в общем файле), даже не изменив мои malloc и бесплатные вызовы.;
Создание функций malloc / free, которые работают со встроенной кучей FreeRTOS, довольно просто. Мы просто завершаем вызовы pvPortMalloc / pvPortFree:
void* malloc(size_t size)
{
void* ptr = NULL;
if(size > 0)
{
// We simply wrap the FreeRTOS call into a standard form
ptr = pvPortMalloc(size);
} // else NULL if there was an error
return ptr;
}
void free(void* ptr)
{
if(ptr)
{
// We simply wrap the FreeRTOS call into a standard form
vPortFree(ptr);
}
}
Обратите внимание, что: Вы не можете использовать это со схемой кучи # 1, но с другими (2, 3, 4 и 5). Я бы рекомендовал начать использовать portable/MemMang/heap_4.c