Still Enemy 0 29 августа, 2015 Опубликовано 29 августа, 2015 (изменено) · Жалоба В общем, писал я себе, писал прогу, а тут на тебе старый знакомый USBD_malloc. Думал раньше, что обойду его, а нет, настиг проклятый. Данная тема является продолжением Эпопеи в двух частях - Как меня задрали USB дрова от разработчиков STM. А теперь ближе к делу. Разбираясь в неполадках передачи по USB(висит в выделенном цикле, хотя в первый цикл проходит(повезло?)) в нижепоказанной функции, узрел что TxState содержит какое то невероятное число. 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(на нестатическую компилятор ругается при линковке, дескать узрел где то чуть ли не сотню дубликатов этого типа там, где он и не используется даже - явный тупняк): 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 и уж тем более не подключены хедеры с файлами, где эта переменная объявлена. Изменено 30 августа, 2015 пользователем Still Enemy Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 119 30 августа, 2015 Опубликовано 30 августа, 2015 · Жалоба Скорее всего он указывает на кусок мусора.Это как раз вполне нормально. Любое выделение памяти вернет память с мусором. Заполнить его после этого разумными данными - задача программиста. Попробовал создать статическую переменную типа структуры 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). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Still Enemy 0 30 августа, 2015 Опубликовано 30 августа, 2015 · Жалоба Это как раз вполне нормально. Любое выделение памяти вернет память с мусором. Заполнить его после этого разумными данными - задача программиста. Ну я же не такой тупой) я посмотрел, что далее в этой же функции, после разименования указателя, идёт заполнение горемычной структуры. 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). Херога. Если при разыменование указателя всё нормально происходит, значит указатель портится в процессе выполнения проги. Это осложняет дело. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 119 30 августа, 2015 Опубликовано 30 августа, 2015 · Жалоба А разве код(нижеприведённый) не должен спасать ситуацию? #ifndef __USB_CDC_H #define __USB_CDC_H #endif Нет. Он не позволяет повторное включение заголовочного файла в одну единицу трансляции. От включения в разные единицы трансляции он защитить не может и не должен. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Still Enemy 0 31 августа, 2015 Опубликовано 31 августа, 2015 · Жалоба Кароч это дно полное. Оказывается указатель pCDC в функции CDC_Transmit_FS "уничтожается" (не знаю даже как назвать это) знаете кем? Не угадали. ОПТИМИЗАТОРОМ. На Hige - Size. Пруфф. Картинка вообще зачётная, такого оптимизирования я еще не видел. Я могу конешно посетовать на то, что я и сам гавнокодер и оптимизатор на мой гавнокод реагирует однозначным гавнодействием. Но так чтобы игнорировать банальное создание указателя и разыменование, на такое я в осадок выпал. Более того скажу, иногда оптимизировался код на столько отлично, что указатель pCDC указывал вообще на левую структуру, жаль не смог запечатлеть этот момент) Вывод: снизил оптимизацию на Medium и радуюсь. НО если кому не сложно, объясните где я накосячил с кодом, что всё пошло именно по такому пути( у меня есть конешно один вариант на этот счёт: я указатель hUsbDevice_0 не передаю в функцию аргументом, а беру его извне(он объявлен в том же хедаре как глобальный указатель, что и данная функция) и собственно из-за этого оптимизатор указатель "уничтожает")? Всё таки оптимизатором нужно считаться, хоть чуть-чуть. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
esaulenka 5 31 августа, 2015 Опубликовано 31 августа, 2015 · Жалоба Картинка вообще зачётная, такого оптимизирования я еще не видел. Добро пожаловать в реальный мир. Суть его такова, что отладчик корректно показывает буковки-цифирки только при низких уровнях оптимизации. Правильно написанный код при этом работает с любой оптимизацией. Понимать, как именно он работает, приходится по асм-листингу. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 119 31 августа, 2015 Опубликовано 31 августа, 2015 · Жалоба А какое содержимое отладчик показывает в h_UsbDevice_0->pClassData? И отлаживаться нужно бродя по дизассемблерному тексту, да. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Still Enemy 0 31 августа, 2015 Опубликовано 31 августа, 2015 (изменено) · Жалоба А какое содержимое отладчик показывает в h_UsbDevice_0->pClassData? И отлаживаться нужно бродя по дизассемблерному тексту, да. pCDC заменил на pTrans Изменено 31 августа, 2015 пользователем Still Enemy Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 119 31 августа, 2015 Опубликовано 31 августа, 2015 · Жалоба И? Вы же видите, что никто эти данные не затер. Когда понадобится, этот указатель окажется в pCDC. pCDC будет размещен в R7. Сейчас R7 пока занят чем-то другим. Включите оконо дизассемблера, не бойтесь. Походите по шагам в нем. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Still Enemy 0 31 августа, 2015 Опубликовано 31 августа, 2015 · Жалоба И? Вы же видите, что никто эти данные не затер. Когда понадобится, этот указатель окажется в pCDC. pCDC будет размещен в R7. Сейчас R7 пока занят чем-то другим. Включите оконо дизассемблера, не бойтесь. Походите по шагам в нем. В том то и дело, что я не боюсь) Прошел я по шагам на дизасемблере эту строчку(если я вас правильно понял конешно). Пруф Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 119 31 августа, 2015 Опубликовано 31 августа, 2015 · Жалоба Прошел я по шагам на дизасемблере эту строчку(если я вас правильно понял конешно).Не, нужная строчка дальше. После текущей строчки в R7 будет жить offset, сейчас в ней мусор а в конце этого цикла окажется, вероятно, pTrans. pCDC в этот момент еще просто не существует. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Still Enemy 0 31 августа, 2015 Опубликовано 31 августа, 2015 · Жалоба Не, нужная строчка дальше. После текущей строчки в R7 будет жить offset, сейчас в ней мусор а в конце этого цикла окажется, вероятно, pTrans. pCDC в этот момент еще просто не существует. Я извиняюсь, что ввел вас в заблуждение. Но я pCDC заменил на pTrans(я об этом отписывался ранее) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 119 31 августа, 2015 Опубликовано 31 августа, 2015 · Жалоба Я извиняюсь, что ввел вас в заблуждение. Но я pCDC заменил на pTrans(я об этом отписывался ранее)В таком случае, вероятно, ошибся отладчик. По приведенному отрывку мне кажется, что pTrans он загрузил в R8, а показывает R7. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Eddy_Em 1 1 сентября, 2015 Опубликовано 1 сентября, 2015 · Жалоба Советую перейти на libopencm3, там таких косяков нет. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Still Enemy 0 2 сентября, 2015 Опубликовано 2 сентября, 2015 (изменено) · Жалоба Советую перейти на libopencm3, там таких косяков нет. Дайте подумать,пожалуй, нет. Сдача проекта в конце сентября, проект не больно маленький. Разбираться во всех этих вещах по новой мне удовольствия не доставит. Да и вообще, нет уверенности, что в вашем libopencm3 не будет других проблем. Изменено 2 сентября, 2015 пользователем Still Enemy Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться