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

 
 
 
Reply to this topicStart new topic
> Keil и Cortex M4, Складывает данные по невыровненым адресам
prottoss
сообщение Feb 9 2016, 18:53
Сообщение #1


Гуру
******

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



Доброго времени суток.

Сам я 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.gif


--------------------
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Feb 9 2016, 20:10
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Без примера некорректного размещения дать какой-либо комментарий затруднительно.
Go to the top of the page
 
+Quote Post
prottoss
сообщение Feb 10 2016, 01:23
Сообщение #3


Гуру
******

Группа: Свой
Сообщений: 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
 


--------------------
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Feb 10 2016, 01:39
Сообщение #4


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



В файлах нет типов, но на каком основании, например, должен быть выровнен FARCONST UINT8 g_PUSBD_HID_Report[]?
Go to the top of the page
 
+Quote Post
prottoss
сообщение Feb 10 2016, 02:30
Сообщение #5


Гуру
******

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



Цитата(aaarrr @ Feb 10 2016, 07:39) *
В файлах нет типов, но на каком основании, например, должен быть выровнен FARCONST UINT8 g_PUSBD_HID_Report[]?
Я считаю что компилятор должен выровнять адрес массива на том основании, что размер массива больше 3 байт.


--------------------
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Feb 10 2016, 02:38
Сообщение #6


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Остается убедить в этом компилятор sm.gif Нет, не должен, и AAPCS такого не требует.
Go to the top of the page
 
+Quote Post
prottoss
сообщение Feb 10 2016, 03:29
Сообщение #7


Гуру
******

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



Цитата(aaarrr @ Feb 10 2016, 08:38) *
Остается убедить в этом компилятор sm.gif Нет, не должен, и AAPCS такого не требует.
С 8-битным массивом понятно - не должен. Но как быть со структурами данных? Неужели там тоже этого не требуется?


В принципе, я нашел как договорится с компилятором с помощью __attribute__(align(4)). Блин, но я тогда гвоздями прибью этот код к конкретному компилятору

И, опять же не понятно, почему для М3 компилятор данные выравнивает, а для М4 нет?


--------------------
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Feb 10 2016, 05:39
Сообщение #8


Гуру
******

Группа: Модераторы
Сообщений: 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)
Go to the top of the page
 
+Quote Post
prottoss
сообщение Feb 10 2016, 06:42
Сообщение #9


Гуру
******

Группа: Свой
Сообщений: 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;


--------------------
Go to the top of the page
 
+Quote Post
SasaVitebsk
сообщение Feb 10 2016, 06:42
Сообщение #10


Гуру
******

Группа: Свой
Сообщений: 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 бит. Почему?
Go to the top of the page
 
+Quote Post
Alechek
сообщение Feb 10 2016, 07:01
Сообщение #11


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

Группа: Свой
Сообщений: 1 241
Регистрация: 15-11-05
Из: Челябинск
Пользователь №: 10 882



SasaVitebsk, потому что в IAR в документации написано, что тип enum берется наименьший из возможных.
У Вас 2 занчения всего - {0, 1} - они прекрасно вмещаются в 1 байт.

Если не нравится - задайте ручками
typecomport PortType :16;
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Feb 10 2016, 07:21
Сообщение #12


Гуру
******

Группа: Модераторы
Сообщений: 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)
Go to the top of the page
 
+Quote Post
psL
сообщение Feb 10 2016, 09:51
Сообщение #13


Знающий
****

Группа: Свой
Сообщений: 526
Регистрация: 5-08-05
Пользователь №: 7 390



вроде бы у Keil #pragma pack( 4 ) была
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Feb 10 2016, 10:49
Сообщение #14


неотягощённый злом
******

Группа: Свой
Сообщений: 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


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post

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

 


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


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