|
|
  |
Keil и Cortex M4, Складывает данные по невыровненым адресам |
|
|
|
Feb 10 2016, 01:23
|

Гуру
     
Группа: Свой
Сообщений: 2 720
Регистрация: 24-03-05
Пользователь №: 3 659

|
Во вложении файлы, в которых размещены дескрипторы. Ничего особенного - объявлены структуры дескрипторов устройств. Вот функция, которая записывает данные в 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 ( 5.68 килобайт )
Кол-во скачиваний: 6
--------------------
|
|
|
|
|
Feb 10 2016, 05:39
|

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

|
Цитата(prottoss @ Feb 10 2016, 05:29)  Но как быть со структурами данных? Неужели там тоже этого не требуется? Выравнивается любая структура или массив. На это есть совершенно четкие правила. Массив байтов выравнивается на адрес, кратный одному. Массив двухбайтовых целых - на адрес, кратный двум. Адреса начала структур и размер структур выравиваются на адрес, кратный размеру наибольшего члена но не больше требований платформы, то есть 4 байт для ARM. Цитата(prottoss @ Feb 10 2016, 05:29)  В принципе, я нашел как договорится с компилятором с помощью __attribute__(align(4)). Блин, но я тогда гвоздями прибью этот код к конкретному компилятору Да. Цитата(prottoss @ Feb 10 2016, 05:29)  И, опять же не понятно, почему для М3 компилятор данные выравнивает, а для М4 нет? Вероятнее всего там вам просто повезло.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Feb 10 2016, 06:42
|

Гуру
     
Группа: Свой
Сообщений: 2 720
Регистрация: 24-03-05
Пользователь №: 3 659

|
Цитата(Сергей Борщ @ Feb 10 2016, 11:39)  ... Да. Сейчас все изучил, прочитал и понял - где ошибался. Но. Ладно - в Keil мне повезло с одним проектом. В IAR повезло с двумя??? Сроду никогда таким везучим не был. Вспомнил. До этого делал еще один проект с STM32L151 год назад - стек USB такой же - свой, самописный. Те же структуры и данные. ХардФолтов не было точно. И еще один проект делал тоже год назад но на STM32F103. На этом же стеке, но в IAR - и тоже без проблем. Вот и привык, что компилятор сам все адреса выравнивает... Т.е. вылезло только вчера и только на М4 и только на Keil. Цитата(Сергей Борщ @ Feb 10 2016, 11:39)  Выравнивается любая структура или массив. Но, в принципе, чтобы уйти от __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;
--------------------
|
|
|
|
|
Feb 10 2016, 06:42
|
Гуру
     
Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521

|
Сергей Борщ, а можно я один вопрос задам. Тему новую не хочется постить. Компилятор 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 бит. Почему?
|
|
|
|
|
Feb 10 2016, 07:21
|

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

|
Цитата(prottoss @ Feb 10 2016, 08:42)  Но, в принципе, чтобы уйти от __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; Цитата(SasaVitebsk @ Feb 10 2016, 08:42)  Вроде бы как читал, что любой enum компилятор определяет как тип int. То есть для данной платформы это должно быть 16 бит. Но по факту в данной структуре это 8 бит. Почему? У компилятора есть галочка "делать по Стандарту или короткие enum". Короткие мне кажутся более удобными. В конце концов можно в enum добавить лишний член со значением 0xFFFF. А в целом, переходите на плюсы - там можно указать явно Код enum typecomport_t : uint16_t { RS232, RS485, }; не считая остальных вкусняшек.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Feb 10 2016, 10:49
|

неотягощённый злом
     
Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643

|
Цитата(prottoss @ Feb 10 2016, 06:29)  Блин, но я тогда гвоздями прибью этот код к конкретному компилятору Чтобы этого не было нужна ещё одна прослоечка, скрывающая все нюансы различных компиляторов... Код #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
--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|