Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Keil и Cortex M4
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
prottoss
Доброго времени суток.

Сам я 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
aaarrr
Без примера некорректного размещения дать какой-либо комментарий затруднительно.
prottoss
Во вложении файлы, в которых размещены дескрипторы. Ничего особенного - объявлены структуры дескрипторов устройств.
Вот функция, которая записывает данные в 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)
aaarrr
В файлах нет типов, но на каком основании, например, должен быть выровнен FARCONST UINT8 g_PUSBD_HID_Report[]?
prottoss
Цитата(aaarrr @ Feb 10 2016, 07:39) *
В файлах нет типов, но на каком основании, например, должен быть выровнен FARCONST UINT8 g_PUSBD_HID_Report[]?
Я считаю что компилятор должен выровнять адрес массива на том основании, что размер массива больше 3 байт.
aaarrr
Остается убедить в этом компилятор sm.gif Нет, не должен, и AAPCS такого не требует.
prottoss
Цитата(aaarrr @ Feb 10 2016, 08:38) *
Остается убедить в этом компилятор sm.gif Нет, не должен, и AAPCS такого не требует.
С 8-битным массивом понятно - не должен. Но как быть со структурами данных? Неужели там тоже этого не требуется?


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

И, опять же не понятно, почему для М3 компилятор данные выравнивает, а для М4 нет?
Сергей Борщ
Цитата(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 нет?
Вероятнее всего там вам просто повезло.
prottoss
Цитата(Сергей Борщ @ 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;
SasaVitebsk
Сергей Борщ, а можно я один вопрос задам. Тему новую не хочется постить.
Компилятор 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
SasaVitebsk, потому что в IAR в документации написано, что тип enum берется наименьший из возможных.
У Вас 2 занчения всего - {0, 1} - они прекрасно вмещаются в 1 байт.

Если не нравится - задайте ручками
typecomport PortType :16;
Сергей Борщ
Цитата(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,
};
не считая остальных вкусняшек.
psL
вроде бы у Keil #pragma pack( 4 ) была
demiurg_spb
Цитата(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
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.