prottoss 0 9 февраля, 2016 Опубликовано 9 февраля, 2016 · Жалоба Доброго времени суток. Сам я Keil не использую, но была необходимость сделать проект именно на этом компиляторе. Проект собран под два проца - первый STM32F107 (Cortex M3) второй под STM32L475 (Cortex M4). Проект связан с передачей данных по USB с использованием встроенного в МК USB OTG модуля, по этому в проекте есть объявленные в виде структур данные всевозможных USB дескрипторов. Так вот, при работе программы под М3 глюков не наблюдалось и он был перенесен на М4. Тут начались глюки. Пр передаче первой же послыки (т.е. еще на этапе нумерации) по USB проц падает в HardFault. Копание показало, что Keil, при использованиии первого МК (М3) размещает все данные по выровненным на 32-бит адресам. При компилировании проекта под М4 он размещает данные с выравниванием в 16-бит... Как так то? или я чего то не понимаю/не знаю? В IAR проект под М3 проверял, под М4 с целевым процом (STM32L475) нет, но адреса расположены с правильным выравниванием. С другим МК - STM32F407 проект работает нормально. Четогдето в Keil подкрутить нужно? Или мне? :cranky: Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aaarrr 69 9 февраля, 2016 Опубликовано 9 февраля, 2016 · Жалоба Без примера некорректного размещения дать какой-либо комментарий затруднительно. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
prottoss 0 10 февраля, 2016 Опубликовано 10 февраля, 2016 · Жалоба Во вложении файлы, в которых размещены дескрипторы. Ничего особенного - объявлены структуры дескрипторов устройств. Вот функция, которая записывает данные в FIFO IN OTG /******************************************************************************* Put data to EP IN FIFO over SW cycle *******************************************************************************/ static void FIFO_IN_Put(UINT32 volatile *in_fifo, UINT32 const *p_src, INT src_len) { INT w_count = (src_len + 3) >> 2; while(w_count--) *in_fifo = *p_src++; } Программа падает в хардфолт в ней сразу после обращения к данным в указателе p_src сразу же при первом вызове функции. При этом в p_src находится адрес дескриптора устройства. См. картинку. Ниже вырезка из MAP-фала для STM32F107. Видно, что все данные, которым положено быть выровненными - выровнены: g_PUSBD_DeviceDescriptor 0x08002928 Data 18 usbd_desc_device.o(.constdata) g_PUSBD_LanguageStringDescriptor 0x0800293c Data 4 usbd_desc_device.o(.constdata) g_PUSBD_VendorStringDescriptor 0x08002940 Data 18 usbd_desc_device.o(.constdata) g_PUSBD_ProductStringDescriptor 0x08002954 Data 44 usbd_desc_device.o(.constdata) g_PUSBD_SerialStringDescriptor 0x08002980 Data 34 usbd_desc_device.o(.constdata) g_PUSBD_HID_Report 0x080029a2 Data 25 usbd_desc_msd_hid.o(.constdata) g_PUSBD_HID_ReportLen 0x080029bb Data 1 usbd_desc_msd_hid.o(.constdata) g_PUSBD_ConfigDescriptor 0x080029bc Data 64 usbd_desc_msd_hid.o(.constdata) g_PUSBD_MSD_MediaInquiryData 0x080029fc Data 44 usbd_desc_msd_hid.o(.constdata) А это для STM32L475 g_PUSBD_DeviceDescriptor 0x08002348 Data 18 usbd_desc_device.o(.constdata) g_PUSBD_LanguageStringDescriptor 0x0800235a Data 4 usbd_desc_device.o(.constdata) g_PUSBD_VendorStringDescriptor 0x0800235e Data 18 usbd_desc_device.o(.constdata) g_PUSBD_ProductStringDescriptor 0x08002370 Data 44 usbd_desc_device.o(.constdata) g_PUSBD_SerialStringDescriptor 0x0800239c Data 34 usbd_desc_device.o(.constdata) g_PUSBD_HID_Report 0x080023be Data 25 usbd_desc_msd_hid.o(.constdata) g_PUSBD_HID_ReportLen 0x080023d7 Data 1 usbd_desc_msd_hid.o(.constdata) g_PUSBD_ConfigDescriptor 0x080023d8 Data 64 usbd_desc_msd_hid.o(.constdata) g_PUSBD_MSD_MediaInquiryData 0x08002418 Data 44 usbd_desc_msd_hid.o(.constdata) DESCS.ZIP Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aaarrr 69 10 февраля, 2016 Опубликовано 10 февраля, 2016 · Жалоба В файлах нет типов, но на каком основании, например, должен быть выровнен FARCONST UINT8 g_PUSBD_HID_Report[]? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
prottoss 0 10 февраля, 2016 Опубликовано 10 февраля, 2016 · Жалоба В файлах нет типов, но на каком основании, например, должен быть выровнен FARCONST UINT8 g_PUSBD_HID_Report[]?Я считаю что компилятор должен выровнять адрес массива на том основании, что размер массива больше 3 байт. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aaarrr 69 10 февраля, 2016 Опубликовано 10 февраля, 2016 · Жалоба Остается убедить в этом компилятор :) Нет, не должен, и AAPCS такого не требует. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
prottoss 0 10 февраля, 2016 Опубликовано 10 февраля, 2016 · Жалоба Остается убедить в этом компилятор :) Нет, не должен, и AAPCS такого не требует.С 8-битным массивом понятно - не должен. Но как быть со структурами данных? Неужели там тоже этого не требуется? В принципе, я нашел как договорится с компилятором с помощью __attribute__(align(4)). Блин, но я тогда гвоздями прибью этот код к конкретному компилятору И, опять же не понятно, почему для М3 компилятор данные выравнивает, а для М4 нет? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 134 10 февраля, 2016 Опубликовано 10 февраля, 2016 · Жалоба Но как быть со структурами данных? Неужели там тоже этого не требуется?Выравнивается любая структура или массив. На это есть совершенно четкие правила. Массив байтов выравнивается на адрес, кратный одному. Массив двухбайтовых целых - на адрес, кратный двум. Адреса начала структур и размер структур выравиваются на адрес, кратный размеру наибольшего члена но не больше требований платформы, то есть 4 байт для ARM. В принципе, я нашел как договорится с компилятором с помощью __attribute__(align(4)). Блин, но я тогда гвоздями прибью этот код к конкретному компиляторуДа. И, опять же не понятно, почему для М3 компилятор данные выравнивает, а для М4 нет?Вероятнее всего там вам просто повезло. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
prottoss 0 10 февраля, 2016 Опубликовано 10 февраля, 2016 · Жалоба ...Да. Сейчас все изучил, прочитал и понял - где ошибался. Но. Ладно - в Keil мне повезло с одним проектом. В IAR повезло с двумя??? Сроду никогда таким везучим не был. Вспомнил. До этого делал еще один проект с STM32L151 год назад - стек USB такой же - свой, самописный. Те же структуры и данные. ХардФолтов не было точно. И еще один проект делал тоже год назад но на STM32F103. На этом же стеке, но в IAR - и тоже без проблем. Вот и привык, что компилятор сам все адреса выравнивает... Т.е. вылезло только вчера и только на М4 и только на Keil. Выравнивается любая структура или массив. Но, в принципе, чтобы уйти от __attribute__(align(4)) я могу все структуры сделать как union c переменной типа UINT32: #pragma pack(4) typedef struct __Foo { .... } Foo, *p_Foo #pragma pack() union __uFoo { Foo DataStructure; UINT32 dwValue; } uFoo, *p_uFoo; Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
SapegoAL 0 10 февраля, 2016 Опубликовано 10 февраля, 2016 · Жалоба Сергей Борщ, а можно я один вопрос задам. Тему новую не хочется постить. Компилятор IAR. Процессор stm32f407. Допустим я делаю следующее typedef enum TIP_COMPORT {RS232, RS485} typecomport_t; // Типы COM портов ... typedef struct { typecomport_t typecomport; // Тип COM порта uint8_t responseDelay; // Пауза м/у запросом и ответом в мс uint16_t baudrate; // Скорость порта nbitscomport_t nbits; // Число бит в байте paritycomport_t parity; // паритет stopbitscomport_t stopbits; // Число стоп-бит // flowcontrolcomport_t flowcontrol; // тип управления потоком protokolcomport_t protokol; // тип протокола } ComSetting_t; Вроде бы как читал, что любой enum компилятор определяет как тип int. То есть для данной платформы это должно быть 16 бит. Но по факту в данной структуре это 8 бит. Почему? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Alechek 0 10 февраля, 2016 Опубликовано 10 февраля, 2016 · Жалоба SasaVitebsk, потому что в IAR в документации написано, что тип enum берется наименьший из возможных. У Вас 2 занчения всего - {0, 1} - они прекрасно вмещаются в 1 байт. Если не нравится - задайте ручками typecomport PortType :16; Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 134 10 февраля, 2016 Опубликовано 10 февраля, 2016 · Жалоба Но, в принципе, чтобы уйти от __attribute__(align(4)) я могу все структуры сделать как union c переменной типа UINT32: Да, можете. Я иногда использую анонимные структуры: typedef union { struct { uint8_t Member_a; uint32_t Memeber_b; ..... } __attribute__((__packed__)); uint32_t Raw[1]; } foo; foo Foo, *p_Foo; Вроде бы как читал, что любой enum компилятор определяет как тип int. То есть для данной платформы это должно быть 16 бит. Но по факту в данной структуре это 8 бит. Почему? У компилятора есть галочка "делать по Стандарту или короткие enum". Короткие мне кажутся более удобными. В конце концов можно в enum добавить лишний член со значением 0xFFFF. А в целом, переходите на плюсы - там можно указать явно enum typecomport_t : uint16_t { RS232, RS485, }; не считая остальных вкусняшек. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
psL 0 10 февраля, 2016 Опубликовано 10 февраля, 2016 · Жалоба вроде бы у Keil #pragma pack( 4 ) была Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
demiurg_spb 0 10 февраля, 2016 Опубликовано 10 февраля, 2016 · Жалоба Блин, но я тогда гвоздями прибью этот код к конкретному компиляторуЧтобы этого не было нужна ещё одна прослоечка, скрывающая все нюансы различных компиляторов... #ifndef _COMPILER_H_ #define _COMPILER_H_ 1 #if defined(__GNUC__) # include "compiler_gcc.h" #elif defined(__CC_ARM) # include "compiler_arm.h" #else # error unsuported compiler! #endif #endif Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться