реклама на сайте
подробности

 
 
 
Reply to this topicStart new topic
> STM32F105 и кривой Malloc
Still Enemy
сообщение Aug 29 2015, 20:26
Сообщение #1


Участник
*

Группа: Участник
Сообщений: 66
Регистрация: 29-01-15
Из: Нижний Новгород
Пользователь №: 84 817



В общем, писал я себе, писал прогу, а тут на тебе старый знакомый USBD_malloc. Думал раньше, что обойду его, а нет, настиг проклятый. Данная тема является продолжением Эпопеи в двух частях - Как меня задрали USB дрова от разработчиков STM.
А теперь ближе к делу.
Разбираясь в неполадках передачи по USB(висит в выделенном цикле, хотя в первый цикл проходит(повезло?)) в нижепоказанной функции, узрел что TxState содержит какое то невероятное число.
CODE
uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len)
{
USBD_CDC_HandleTypeDef *pCDC =
(USBD_CDC_HandleTypeDef *)hUsbDevice_0->pClassData;
uint16_t offset = 0;
while (offset < Len)
{
if ((Len-offset)<TX_BUFF_SIZE)
{
while(pCDC->TxState);
USBD_CDC_SetTxBuffer(hUsbDevice_0, Buf + offset, Len-offset);
if (USBD_CDC_TransmitPacket(hUsbDevice_0) != USBD_OK)
return USBD_FAIL;
while(pCDC->TxState);
break;
}
while(pCDC->TxState);
USBD_CDC_SetTxBuffer(hUsbDevice_0, Buf + offset, TX_BUFF_SIZE);
if (USBD_CDC_TransmitPacket(hUsbDevice_0) != USBD_OK)
return USBD_FAIL;
while(pCDC->TxState);
offset+=0x40;
}
return USBD_OK;}

Думаю, что это неправильная инициализация указателя pClassData. Скорее всего он указывает на кусок мусора. Потому что собственно он инициализируется вот так(для тех кто в танке и не стал читать ссыль на предыдущую часть Эпопеи):
Код
  pdev->pClassData = USBD_malloc(sizeof (USBD_CDC_HandleTypeDef));

Сам малок выглядит вот так:
Код
#define USBD_malloc               (uint32_t *)USBD_static_malloc
void *USBD_static_malloc(uint32_t size)
{
  static uint8_t mem[sizeof(USBD_CDC_HandleTypeDef)];
  return mem;
}

Как все успели заметить - это гавнокод(КО не дремлет). В связи с этим, хочу решить проблему иным способом, так чтобы работало всё.
Попробовал создать статическую переменную типа структуры USBD_CDC_HandleTypeDef(на нестатическую компилятор ругается при линковке, дескать узрел где то чуть ли не сотню дубликатов этого типа там, где он и не используется даже - явный тупняк):
CODE
typedef struct
{
uint32_t data[CDC_DATA_HS_MAX_PACKET_SIZE/4]; /* Force 32bits alignment */
uint8_t CmdOpCode;
uint8_t CmdLength;
uint8_t *RxBuffer;
uint8_t *TxBuffer;
uint32_t RxLength;
uint32_t TxLength;

__IO uint32_t TxState;
__IO uint32_t RxState;
}
USBD_CDC_HandleTypeDef;

static USBD_CDC_HandleTypeDef USBD_CDC_Handle;

Также убрал малок:
Код
pdev->pClassData = &USBD_CDC_Handle;

Работать это конешно не стало, как и предполагалось, всё тоже самое что и до замены малока.
Как бы решить эту проблему, подскажите)
P.s. На буржуйском форуме пишут про баги для STM32F4 Discovery. Якобы явное приведение типа указателя к void* и расширение heap поможет. Сомнительно. Но я к сожалению до понедельника не смогу удостовериться, так как прибор на работе

Update
И кто-нибудь сможет ответить на вопрос, почему если я создам глобальную (не статическую как показано выше) переменную типа USBD_CDC_HandleTypeDef, то вылетают такие ошибки:
Код
Error[Li006]: duplicate definitions for "USBD_CDC_Handle"; in "G:\Работа\FirmWare0.02\EWARM\FirmWare0.02 Configuration\Obj\ADC.o", and "G:\Работа\FirmWare0.02\EWARM\FirmWare0.02 Configuration\Obj\M25P128.o"
Error[Li006]: duplicate definitions for "USBD_CDC_Handle"; in "G:\Работа\FirmWare0.02\EWARM\FirmWare0.02 Configuration\Obj\ADC.o", and "G:\Работа\FirmWare0.02\EWARM\FirmWare0.02 Configuration\Obj\main.o"
Error[Li006]: duplicate definitions for "USBD_CDC_Handle"; in "G:\Работа\FirmWare0.02\EWARM\FirmWare0.02 Configuration\Obj\ADC.o", and "G:\Работа\FirmWare0.02\EWARM\FirmWare0.02 Configuration\Obj\usb_device.o"
Error[Li006]: duplicate definitions for "USBD_CDC_Handle"; in "G:\Работа\FirmWare0.02\EWARM\FirmWare0.02 Configuration\Obj\ADC.o", and "G:\Работа\FirmWare0.02\EWARM\FirmWare0.02 Configuration\Obj\usbd_cdc.o"
Error[Li006]: duplicate definitions for "USBD_CDC_Handle"; in "G:\Работа\FirmWare0.02\EWARM\FirmWare0.02 Configuration\Obj\ADC.o", and "G:\Работа\FirmWare0.02\EWARM\FirmWare0.02 Configuration\Obj\usbd_cdc_if.o"
Error[Li006]: duplicate definitions for "USBD_CDC_Handle"; in "G:\Работа\FirmWare0.02\EWARM\FirmWare0.02 Configuration\Obj\ADC.o", and "G:\Работа\FirmWare0.02\EWARM\FirmWare0.02 Configuration\Obj\usbd_conf.o"
Error while running Linker

что за хрень? в данных файлах нету никакого объявления USBD_CDC_Handle и уж тем более не подключены хедеры с файлами, где эта переменная объявлена.

Сообщение отредактировал Still Enemy - Aug 30 2015, 06:31
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Aug 30 2015, 06:44
Сообщение #2


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(Still Enemy @ Aug 29 2015, 23:26) *
Скорее всего он указывает на кусок мусора.
Это как раз вполне нормально. Любое выделение памяти вернет память с мусором. Заполнить его после этого разумными данными - задача программиста.
Цитата(Still Enemy @ Aug 29 2015, 23:26) *
Попробовал создать статическую переменную типа структуры USBD_CDC_HandleTypeDef(на нестатическую компилятор ругается при линковке, дескать узрел где то чуть ли не сотню дубликатов этого типа там, где он и не используется даже - явный тупняк):
Ругань была совершенно справедливой, это явный ваш тупняк. Вы пытались определить переменную в заголовочном файле. Заголовочный файл включается в несколько исходных файлов (единиц копиляции) методом тупой текстовой подстановки. Получилось, что вы определили одну и ту же переменную в нескольких единицах компиляции. Компилятор понятия не имеет о существовании других единиц компиляции, поэтому честно создал такую переменную в каждой единице. И линкер получил кучу переменных с одинаковым именем. Когда вы добавили static, вы получили еще более веселый результат - вы получили в каждой единице компиляции свою переменную, которая не видна из других единиц компиляции. То есть каждая единица компиляции работала со своей копией переменной. Если смотреть углубленно - то ваш код при этом должен был работать, поскольку прямое обращение к этой переменной у вас происходит только в одном файле, там, где ее адрес присваивается указателю. В остальных местах обращение идет только через указатель и попадает в ту же самую переменную. Остальные копии этой переменной выкинул оптимизатор. Но в общем случае это говнокод еще похуже исходного.

Выкиньте ваше
Код
static USBD_CDC_HandleTypeDef  USBD_CDC_Handle;
. В том файле, где находится строка
Код
  pdev->pClassData = USBD_malloc(sizeof (USBD_CDC_HandleTypeDef));
объявите глобальную переменную
Код
USBD_CDC_HandleTypeDef  USBD_CDC_Handle;
и присвойте ее адрес
Код
  pdev->pClassData = &USBD_CDC_Handle;
После чего на всякий случай закомментируйте USBD_static_malloc чтобы компилятор ругался на все места, где она еще может использоваться.

Однако это скорее всего не поможет. Проблема не здесь. Исходный код с USBD_static_malloc() должен работать, если из него выкинуть free(p).


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
Still Enemy
сообщение Aug 30 2015, 07:15
Сообщение #3


Участник
*

Группа: Участник
Сообщений: 66
Регистрация: 29-01-15
Из: Нижний Новгород
Пользователь №: 84 817



Цитата(Сергей Борщ @ Aug 30 2015, 09:44) *
Это как раз вполне нормально. Любое выделение памяти вернет память с мусором. Заполнить его после этого разумными данными - задача программиста.

Ну я же не такой тупой) я посмотрел, что далее в этой же функции, после разименования указателя, идёт заполнение горемычной структуры.
CODE
static uint8_t USBD_CDC_Init (USBD_HandleTypeDef *pdev,
uint8_t cfgidx)
{
uint8_t ret = 0;
USBD_CDC_HandleTypeDef *hcdc;

if(pdev->dev_speed == USBD_SPEED_HIGH )
{
/* Open EP IN */
USBD_LL_OpenEP(pdev,
CDC_IN_EP,
USBD_EP_TYPE_BULK,
CDC_DATA_HS_IN_PACKET_SIZE);

/* Open EP OUT */
USBD_LL_OpenEP(pdev,
CDC_OUT_EP,
USBD_EP_TYPE_BULK,
CDC_DATA_HS_OUT_PACKET_SIZE);

}
else
{
/* Open EP IN */
USBD_LL_OpenEP(pdev,
CDC_IN_EP,
USBD_EP_TYPE_BULK,
CDC_DATA_FS_IN_PACKET_SIZE);

/* Open EP OUT */
USBD_LL_OpenEP(pdev,
CDC_OUT_EP,
USBD_EP_TYPE_BULK,
CDC_DATA_FS_OUT_PACKET_SIZE);
}
/* Open Command IN EP */
USBD_LL_OpenEP(pdev,
CDC_CMD_EP,
USBD_EP_TYPE_INTR,
CDC_CMD_PACKET_SIZE);


pdev->pClassData = &USBD_CDC_Handle;//USBD_malloc(sizeof (USBD_CDC_HandleTypeDef));

if(pdev->pClassData == NULL)
{
ret = 1;
}
else
{
hcdc = (USBD_CDC_HandleTypeDef*) pdev->pClassData;

/* Init physical Interface components */
((USBD_CDC_ItfTypeDef *)pdev->pUserData)->Init();

/* Init Xfer states */
hcdc->TxState =0;
hcdc->RxState =0;

if(pdev->dev_speed == USBD_SPEED_HIGH )
{
/* Prepare Out endpoint to receive next packet */
USBD_LL_PrepareReceive(pdev,
CDC_OUT_EP,
hcdc->RxBuffer,
CDC_DATA_HS_OUT_PACKET_SIZE);
}
else
{
/* Prepare Out endpoint to receive next packet */
USBD_LL_PrepareReceive(pdev,
CDC_OUT_EP,
hcdc->RxBuffer,
CDC_DATA_FS_OUT_PACKET_SIZE);
}

}
return ret;
}

Цитата
Ругань была совершенно справедливой, это явный ваш тупняк. Вы пытались определить переменную в заголовочном файле. Заголовочный файл включается в несколько исходных файлов (единиц копиляции) методом тупой текстовой подстановки. Получилось, что вы определили одну и ту же переменную в нескольких единицах компиляции.

А разве код(нижеприведённый) не должен спасать ситуацию?
Код
#ifndef __USB_CDC_H
#define __USB_CDC_H
#endif

Цитата
Но в общем случае это говнокод еще похуже исходного.

Согласен, просто сделал первое, что пришло на ум)

Цитата
Однако это скорее всего не поможет. Проблема не здесь. Исходный код с USBD_static_malloc() должен работать, если из него выкинуть free(p).

Херога. Если при разыменование указателя всё нормально происходит, значит указатель портится в процессе выполнения проги. Это осложняет дело.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Aug 30 2015, 09:42
Сообщение #4


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(Still Enemy @ Aug 30 2015, 10:15) *
А разве код(нижеприведённый) не должен спасать ситуацию?
Код
#ifndef __USB_CDC_H
#define __USB_CDC_H
#endif
Нет. Он не позволяет повторное включение заголовочного файла в одну единицу трансляции. От включения в разные единицы трансляции он защитить не может и не должен.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
Still Enemy
сообщение Aug 31 2015, 07:26
Сообщение #5


Участник
*

Группа: Участник
Сообщений: 66
Регистрация: 29-01-15
Из: Нижний Новгород
Пользователь №: 84 817



Кароч это дно полное. Оказывается указатель pCDC в функции CDC_Transmit_FS "уничтожается" (не знаю даже как назвать это) знаете кем? Не угадали. ОПТИМИЗАТОРОМ. На Hige - Size.
Пруфф.

Картинка вообще зачётная, такого оптимизирования я еще не видел. Я могу конешно посетовать на то, что я и сам гавнокодер и оптимизатор на мой гавнокод реагирует однозначным гавнодействием. Но так чтобы игнорировать банальное создание указателя и разыменование, на такое я в осадок выпал. Более того скажу, иногда оптимизировался код на столько отлично, что указатель pCDC указывал вообще на левую структуру, жаль не смог запечатлеть этот момент)
Вывод: снизил оптимизацию на Medium и радуюсь. НО если кому не сложно, объясните где я накосячил с кодом, что всё пошло именно по такому пути( у меня есть конешно один вариант на этот счёт: я указатель hUsbDevice_0 не передаю в функцию аргументом, а беру его извне(он объявлен в том же хедаре как глобальный указатель, что и данная функция) и собственно из-за этого оптимизатор указатель "уничтожает")? Всё таки оптимизатором нужно считаться, хоть чуть-чуть.
Go to the top of the page
 
+Quote Post
esaulenka
сообщение Aug 31 2015, 07:57
Сообщение #6


Профессионал
*****

Группа: Свой
Сообщений: 1 032
Регистрация: 13-03-08
Из: Маськва
Пользователь №: 35 877



Цитата(Still Enemy @ Aug 31 2015, 10:26) *
Картинка вообще зачётная, такого оптимизирования я еще не видел.


Добро пожаловать в реальный мир. Суть его такова, что отладчик корректно показывает буковки-цифирки только при низких уровнях оптимизации.
Правильно написанный код при этом работает с любой оптимизацией. Понимать, как именно он работает, приходится по асм-листингу.


--------------------
Тут обсуждается творческий порыв, а не соответствие каким-либо стандартам ©
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Aug 31 2015, 08:53
Сообщение #7


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



А какое содержимое отладчик показывает в h_UsbDevice_0->pClassData? И отлаживаться нужно бродя по дизассемблерному тексту, да.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
Still Enemy
сообщение Aug 31 2015, 09:49
Сообщение #8


Участник
*

Группа: Участник
Сообщений: 66
Регистрация: 29-01-15
Из: Нижний Новгород
Пользователь №: 84 817



Цитата(Сергей Борщ @ Aug 31 2015, 12:53) *
А какое содержимое отладчик показывает в h_UsbDevice_0->pClassData? И отлаживаться нужно бродя по дизассемблерному тексту, да.

pCDC заменил на pTrans


Сообщение отредактировал Still Enemy - Aug 31 2015, 12:53
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Aug 31 2015, 10:08
Сообщение #9


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



И? Вы же видите, что никто эти данные не затер. Когда понадобится, этот указатель окажется в pCDC. pCDC будет размещен в R7. Сейчас R7 пока занят чем-то другим. Включите оконо дизассемблера, не бойтесь. Походите по шагам в нем.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
Still Enemy
сообщение Aug 31 2015, 10:19
Сообщение #10


Участник
*

Группа: Участник
Сообщений: 66
Регистрация: 29-01-15
Из: Нижний Новгород
Пользователь №: 84 817



Цитата(Сергей Борщ @ Aug 31 2015, 14:08) *
И? Вы же видите, что никто эти данные не затер. Когда понадобится, этот указатель окажется в pCDC. pCDC будет размещен в R7. Сейчас R7 пока занят чем-то другим. Включите оконо дизассемблера, не бойтесь. Походите по шагам в нем.

В том то и дело, что я не боюсь) Прошел я по шагам на дизасемблере эту строчку(если я вас правильно понял конешно).
Пруф
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Aug 31 2015, 12:47
Сообщение #11


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(Still Enemy @ Aug 31 2015, 13:19) *
Прошел я по шагам на дизасемблере эту строчку(если я вас правильно понял конешно).
Не, нужная строчка дальше. После текущей строчки в R7 будет жить offset, сейчас в ней мусор а в конце этого цикла окажется, вероятно, pTrans. pCDC в этот момент еще просто не существует.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
Still Enemy
сообщение Aug 31 2015, 12:52
Сообщение #12


Участник
*

Группа: Участник
Сообщений: 66
Регистрация: 29-01-15
Из: Нижний Новгород
Пользователь №: 84 817



Цитата(Сергей Борщ @ Aug 31 2015, 16:47) *
Не, нужная строчка дальше. После текущей строчки в R7 будет жить offset, сейчас в ней мусор а в конце этого цикла окажется, вероятно, pTrans. pCDC в этот момент еще просто не существует.

Я извиняюсь, что ввел вас в заблуждение. Но я pCDC заменил на pTrans(я об этом отписывался ранее)
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Aug 31 2015, 12:56
Сообщение #13


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(Still Enemy @ Aug 31 2015, 15:52) *
Я извиняюсь, что ввел вас в заблуждение. Но я pCDC заменил на pTrans(я об этом отписывался ранее)
В таком случае, вероятно, ошибся отладчик. По приведенному отрывку мне кажется, что pTrans он загрузил в R8, а показывает R7.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
Эдди
сообщение Sep 1 2015, 09:58
Сообщение #14


Знающий
****

Группа: Участник
Сообщений: 825
Регистрация: 16-04-15
Из: КЧР, Нижний Архыз
Пользователь №: 86 250



Советую перейти на libopencm3, там таких косяков нет.
Go to the top of the page
 
+Quote Post
Still Enemy
сообщение Sep 2 2015, 11:27
Сообщение #15


Участник
*

Группа: Участник
Сообщений: 66
Регистрация: 29-01-15
Из: Нижний Новгород
Пользователь №: 84 817



Цитата(Эдди @ Sep 1 2015, 13:58) *
Советую перейти на libopencm3, там таких косяков нет.

Дайте подумать,пожалуй, нет. Сдача проекта в конце сентября, проект не больно маленький. Разбираться во всех этих вещах по новой мне удовольствия не доставит. Да и вообще, нет уверенности, что в вашем libopencm3 не будет других проблем.

Сообщение отредактировал Still Enemy - Sep 2 2015, 11:30
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 18th July 2025 - 20:57
Рейтинг@Mail.ru


Страница сгенерированна за 0.01491 секунд с 7
ELECTRONIX ©2004-2016