Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: STM32F0xxx USB без HAL
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
alexf
Делаю устройство на STM32F070. Сгенерировал код с USB CDC на кубе, и USB работает (пока) без нареканий. А вот попытки использовать HAL для других целей, скажем USART, создают больше проблем, чем решают. Для меня. Наверное, пользоваться не умею. В результате мешанина из HAL с прямыми обращениями к регистрам. Боюсь это меня рано или поздно узусит за задницу.

Так вот вопрос. Есть ли пример USB CDC без HAL? На F103 легко находится. Уже давно использовал. А для F0? Много ли надо менять, если нет готового кода?
Allregia
Цитата(alexf @ Oct 23 2016, 04:03) *
В результате мешанина из HAL с прямыми обращениями к регистрам. Боюсь это меня рано или поздно узусит за задницу.


Если оно не под RTOS или подобным работает, то не укусит. Я, если нет задачи вместиться в небольшую память, часто отдаю HALу или SPL все настройки и инициализации - так оно проще и легче менять их Кубом, в случае чего.
А основную работу - непосредственно в регистры.
AHTOXA
Цитата(alexf @ Oct 23 2016, 08:03) *
Есть ли пример USB CDC без HAL?

Пример.
alexf
Цитата(AHTOXA @ Oct 23 2016, 00:36) *


Спасибо! Уже нашел еще один для F072. Разбираюсь с клоками: у 070 USB совсем по другому тактируется.

P.S. Похоже это то же пример, что я нашел "STM32F0x2_USB-FS-Device_Lib V1.0.0". Там 070 не предусмотрен. После нескольких часов переписывания инклудов он собрался, но не работает. Что-то я не так сделал. Ну да ладно, объем кода почти тот же как с HAL. HAL и оставлю, раз работает. Но каие же чудеса в HAL накрутили с USART! Пришлось выкинуть и заменить на несколько строчек прямой работы.

Еще надо разобраться, как отправлять данные. Если позвать USBD_CDC_TransmitPacket, он будет ждать, пока хост не попросит пакет. А если за это время еще данных поступило? Скорее всего не страшно, соберу в другой буффер. Но правильнее копировать буффер по SOF.
Genadi Zawidowski
USBD_LL_Transmit вообще-то вызывается в обработчике прерывания (callback) USBD_LL_DataInStage, который возникает именно тогда, когда хост попросил пакет. Если данных нет, вызвать USBD_LL_Transmit с нулевым размером данных. Если есть - отдать всё что накопленно.
johnshadow
использую libopencm3 на stm32f072 - CDC (для основной проги) и MassStorage (для бутлоадера).
Сергей Борщ
QUOTE (johnshadow @ Oct 24 2016, 11:20) *
использую libopencm3 на stm32f072
Мы рады за вас.
johnshadow
Цитата(Сергей Борщ @ Oct 24 2016, 13:01) *
Мы рады за вас.

Всегда пожалуйста.
esaulenka
Цитата(Сергей Борщ @ Oct 24 2016, 13:01) *
Мы рады за вас.

Сергей, а какие претензии-то?
libopencm3 - действительно, весьма приятная библиотека.
Тот же USB написан значительно проще и понятнее, чем в обоих вариантах ST'шных библиотек.

И слоёв там меньше, и профили не засунуты в сердину библиотеки. В общем, я тоже рекомендую, даже с учётом отсутствия там STM32F07x "из коробки"
johnshadow
Пример CDC для F072 можно подсмотреть в форке kuldeepdhaka/libopencm3-examples в ветке example/pwm/stm32f07.
под stm32f0xx пришлось в паре мест слегка поправить, т.к. получал hardfault по доступу к невыравненным данным.
типа такого:
Код
diff --git a/libopencm3/usb/usb_standard.c b/libopencm3/usb/usb_standard.c
index d94ceed..da47391 100644
--- a/libopencm3/usb/usb_standard.c
+++ b/libopencm3/usb/usb_standard.c
@@ -130,7 +130,9 @@ static uint16_t build_config_descriptor(usbd_device *usbd_dev,
    }

    /* Fill in wTotalLength. */
-    *(uint16_t *)(tmpbuf + 2) = totallen;
+    //*(uint16_t *)(tmpbuf + 2) = totallen;
+    *(tmpbuf + 2) = totallen & 0xFF;
+    *(tmpbuf + 3) = totallen >> 8;

    return total;
}

я так и не понял почему компилятор не обрабатывает такие ситуации сам (gcc-arm-embedded 5.4 2016q2). может кто из местных объяснит.
Allregia
Цитата(johnshadow @ Oct 25 2016, 07:30) *
я так и не понял почему компилятор не обрабатывает такие ситуации сам (gcc-arm-embedded 5.4 2016q2). может кто из местных объяснит.

А если взять IAR или KEil - тоже самое происходит?
Сергей Борщ
QUOTE (johnshadow @ Oct 25 2016, 09:30) *
я так и не понял почему компилятор не обрабатывает такие ситуации сам
Потому что не обязан. Вы же хотите, чтобы ваши программы были маленькими и быстрыми. Используете явное приведение типов - вся ответственность на вас.
Kabdim
Цитата(johnshadow @ Oct 25 2016, 09:30) *
я так и не понял почему компилятор не обрабатывает такие ситуации сам (gcc-arm-embedded 5.4 2016q2). может кто из местных объяснит.

Потому что компилятор априори верит что программист знает что делает, если есть явное указание на операцию. Зря конечно верит biggrin.gif . Ну а вы сами же и привели к указателю на 2ухбайтное значение, которое опять же должно быть выровнено. Кстати патч на мой вкус не очень. В таких случая лучше либо использовать memcpy (в релизе его соптимизируют в инлайн), либо код вроде такого:
Код
typedef struct {
    uint16_t value;
} __attribute__((packed)) unaligned_uint16;

((unaligned_uint16*)bla_bla).value = ...;

В вашем решении много битовых операций на ровном месте.
johnshadow
Цитата(Сергей Борщ @ Oct 25 2016, 10:41) *
Потому что не обязан. Вы же хотите, чтобы ваши программы были маленькими и быстрыми. Используете явное приведение типов - вся ответственность на вас.

Я просто думал, что для cortex-m0 компилятор генерирует безопасный код в тех случаях когда адрес переменной на момент компиляции не известен. Тогда мне не ясно назначение опции -mno-unaligned-access. Ладно бы hardfault возникал при оптимизациях Os или O3,
где побайтовый доступ потенциально приводил бы к раздутию кода или снижению производительности.

2Allregia: Нет, на IAR\KEil не проверял.

Цитата(Kabdim @ Oct 25 2016, 11:10) *
Кстати патч на мой вкус не очень. В таких случая лучше либо использовать memcpy (в релизе его соптимизируют в инлайн), либо код вроде такого:
...
В вашем решении много битовых операций на ровном месте.

memcpy при оптимизациях Os\O3 меня уже пару раз подводила. решение со структурой действительно потенциально быстрее, но
не будет ли генерироваться ассемблерный код, который будет вылетать при невыровненном доступе?
Kabdim
Цитата(johnshadow @ Oct 25 2016, 11:49) *
memcpy при оптимизациях Os\O3 меня уже пару раз подводила. решение со структурой действительно потенциально быстрее, но
не будет ли генерироваться ассемблерный код, который будет вылетать при невыровненном доступе?

Не будет. Если конечно не играть озвученной опцией -mno-unaligned-access.
AHTOXA
Цитата(Kabdim @ Oct 25 2016, 13:10) *
Код
typedef struct {
    uint16_t value;
} __attribute__((packed)) unaligned_uint16;

((unaligned_uint16*)bla_bla).value = ...;

В вашем решении много битовых операций на ровном месте.

Да ладно вам стращатьsm.gif Современные компиляторы отлично оптимизируют конструкции вида
Код
    *(tmpbuf + 2) = totallen & 0xFF;
    *(tmpbuf + 3) = totallen >> 8;

Думаю, что код, сгенерированный компилятором в вашем варианте и в этом будет эквивалентен. Зато этот вариант понятнее, к тому же он переносим.
Сергей Борщ
QUOTE (johnshadow @ Oct 25 2016, 11:49) *
memcpy при оптимизациях Os\O3 меня уже пару раз подводила.
Интересно. Когда подведет еще раз - выложите сюда, вероятнее всего вы просто не умеете ее готовить.
Kabdim
Цитата(AHTOXA @ Oct 25 2016, 13:21) *
Да ладно вам стращатьsm.gif Современные компиляторы отлично оптимизируют конструкции вида

Поинт был не в том. sm.gif Согласен что эффективность будет одинаковая. Но читать код как у ТСа мне хуже чем другие варианты. Я его просто буду раз десять перечитывать что бы точно убедится что не меняется порядок байт, в др. вариантах назначение кода сразу очевидно. Во-вторых в варианте ТСа куча чисел. В спокойной обстановке всё конечно ясно, но порой код редактирует, к примеру, коллега автора и находится он не в лучшем состоянии ума и тогда возможны любые чудеса - уже испытывал это.

Цитата(AHTOXA @ Oct 25 2016, 13:21) *
Зато этот вариант понятнее, к тому же он переносим.

Для упрощения примера я вставил сразу gcc'шный вариант, но в боевом это макросы в зависимости от платформы. Так что упакованная структура так же переносима.
johnshadow
Цитата(Сергей Борщ @ Oct 25 2016, 13:26) *
Интересно. Когда подведет еще раз - выложите сюда, вероятнее всего вы просто не умеете ее готовить.

Возможно. Мне тяжело сейчас предоставить "живой" пример - дело было два-три года назад.
Помню, что ошибка проявлялась при совместном использовании оптимизации по размеру и LinkTimeOptimization (Os и flto).
Проект был по CooCox и они только добавили опцию LTO у себя в настройках компиляции.
Обошел ее используя не библиотечную реализацию:
Код
__attribute__((used)) void * memcpy(void * d1, const void * s1, size_t n) {
    char * d;
    const char * s;
    volatile size_t n1 = n;
    s = s1;
    d = d1;
    while (n1--)
        *d++ = *s++;
    return d1;
}

"помогало" именно создание volatile'ной переменной и дальнейшая работа с ней.
в противном случае (при использовании аргументной переменной n) бесконечно висел в while - уменьшение переменной не происходило.
причем висело не в моем коде, а внутри функций freertos (тогда то ли 6, то ли 7 версии).
понимаю, что это все выглядит как рассказ про йети, но... laughing.gif

Kabdim
Удалил, попутал со знаковым переполнением.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.