STM32 и USB (практика)
- Eddy_Em
- Собутыльник Кота
- Сообщения: 2516
- Зарегистрирован: Пт июл 12, 2019 22:52:01
- Контактная информация:
Re: STM32 и USB (практика)
[uquote="VladislavS",url="/forum/viewtopic.php?p=4004250#p4004250"]чем отличается SET_FEAUTRE от SET_REPORT наверняка даже не подозревает.[/uquote]
Не подозреваю. Я не использую ненужные хрени. Только то, что нужно для нормальной работы! CDC я тоже сначала, как идиот, насмотревшись чужих решений, сделал, выделяя физическую EP на INTERRUPT, но ее обработчик ничего не делал (как и у всех). Тогда я подумал: а на кой мне черт выделять полезную EP на ничто? И перестал это делать: в конфигурации INTERRUPT EP указана, а фактически ее нет (т.к. она не нужна). И прекрасно все работает. Проверял и на компьютере, и на андроиде. На игровых приставках не проверял, т.к. бессмысленно.
Не подозреваю. Я не использую ненужные хрени. Только то, что нужно для нормальной работы! CDC я тоже сначала, как идиот, насмотревшись чужих решений, сделал, выделяя физическую EP на INTERRUPT, но ее обработчик ничего не делал (как и у всех). Тогда я подумал: а на кой мне черт выделять полезную EP на ничто? И перестал это делать: в конфигурации INTERRUPT EP указана, а фактически ее нет (т.к. она не нужна). И прекрасно все работает. Проверял и на компьютере, и на андроиде. На игровых приставках не проверял, т.к. бессмысленно.
- Реклама
- COKPOWEHEU
- Говорящий с текстолитом
- Сообщения: 1525
- Зарегистрирован: Чт июн 10, 2010 20:11:19
Re: STM32 и USB (практика)
А как вы без нее посылаете всякие RTS, CTS и прочие? Я так понял, что она нужна чтобы экстренно предупредить хост что данные больше не помещаются, что потеряна несущая или что-то в этом роде.сделал, выделяя физическую EP на INTERRUPT, но ее обработчик ничего не делал
- Eddy_Em
- Собутыльник Кота
- Сообщения: 2516
- Зарегистрирован: Пт июл 12, 2019 22:52:01
- Контактная информация:
Re: STM32 и USB (практика)
[uquote="COKPOWEHEU",url="/forum/viewtopic.php?p=4004330#p4004330"]А как вы без нее посылаете всякие RTS, CTS и прочие?[/uquote]
Никак. Я ими не пользуюсь. Даже на честном RS-232 никогда не пользовался аппаратным контролем.
А вообще, у меня есть weak-обработчик clstate_handler, который вызывается при получении от хоста SET_CONTROL_LINE_STATE. А GET_CONTROL_LINE_STATE я не использую.
Никак. Я ими не пользуюсь. Даже на честном RS-232 никогда не пользовался аппаратным контролем.
А вообще, у меня есть weak-обработчик clstate_handler, который вызывается при получении от хоста SET_CONTROL_LINE_STATE. А GET_CONTROL_LINE_STATE я не использую.
- COKPOWEHEU
- Говорящий с текстолитом
- Сообщения: 1525
- Зарегистрирован: Чт июн 10, 2010 20:11:19
Re: STM32 и USB (практика)
Ну вот и ответНикак. Я ими не пользуюсь.
Но иногда они все же нужны, пусть и для связи с антикварным оборудованием. Вы видели, наверное, на Хабре статью, где какой-то парень изобретал USB - 3xUART со всеми управляющими линиями. Значит, иногда необходимость возникает.
- VladislavS
- Собутыльник Кота
- Сообщения: 2562
- Зарегистрирован: Вт май 01, 2018 19:44:47
Re: STM32 и USB (практика)
Мои реализации CDC и Custom HID (работает с USB HID Demonstrator). Работать должно на STM32F0, STM32L0, STM32F1, STM32F3, STM32G4. Разделено на уровни Hardware <-> USB Device <-> USB Class. Проекты IAR, Keil, VisualGDB, makefile GCC linux и win. Кто не любит плюсы, можете не смотреть.
- Реклама
- Eddy_Em
- Собутыльник Кота
- Сообщения: 2516
- Зарегистрирован: Пт июл 12, 2019 22:52:01
- Контактная информация:
Re: STM32 и USB (практика)
[uquote="COKPOWEHEU",url="/forum/viewtopic.php?p=4004361#p4004361"]Но иногда они все же нужны, пусть и для связи с антикварным оборудованием.[/uquote]
Ну так мой CDC предназначен для организации "общения" с МК. Я не преследую цели из дорогущего МК сделать элементарный преобразователь USB<>UART или USB<>RS-232!!! Такие преобразователи можно недорого на али купить (правда, в случае с RS-232 дешевле сделать самому из PL2303 и MAX3232, готовые адово дорогие - от 400р за штучку на али).
Я даже не CDC использую, т.к. мне не нравится /dev/ttyACMx в именовании + на мастдайках вроде бубунты по дефолту запущен modemd, который ACM пытается перехватить на себя и занимает порт. Я эмулирую PL2303, благодаря чему девайс именуется как нормальный /dev/ttyUSBx и никакой modemd в мастдайках его не пытается заблокировать.
Что до HID, сделал его развлекухи ради, т.к. у меня вообще нет задач, требующих эмуляции мыши или клавиатуры. Вообще не представляю себе, зачем кому-то может понадобится HID, если только он не изготавливает кастомные клавы-мыши-джойстики.
P.S. COKPOWEHEU, за уход от калокуба - однозначный плюс. Теперь остается вам еще вместо игровой прошивки поставить себе операционную систему (хотя бы мастдайку вроде бубунты или красношапки).
Ну так мой CDC предназначен для организации "общения" с МК. Я не преследую цели из дорогущего МК сделать элементарный преобразователь USB<>UART или USB<>RS-232!!! Такие преобразователи можно недорого на али купить (правда, в случае с RS-232 дешевле сделать самому из PL2303 и MAX3232, готовые адово дорогие - от 400р за штучку на али).
Я даже не CDC использую, т.к. мне не нравится /dev/ttyACMx в именовании + на мастдайках вроде бубунты по дефолту запущен modemd, который ACM пытается перехватить на себя и занимает порт. Я эмулирую PL2303, благодаря чему девайс именуется как нормальный /dev/ttyUSBx и никакой modemd в мастдайках его не пытается заблокировать.
Что до HID, сделал его развлекухи ради, т.к. у меня вообще нет задач, требующих эмуляции мыши или клавиатуры. Вообще не представляю себе, зачем кому-то может понадобится HID, если только он не изготавливает кастомные клавы-мыши-джойстики.
P.S. COKPOWEHEU, за уход от калокуба - однозначный плюс. Теперь остается вам еще вместо игровой прошивки поставить себе операционную систему (хотя бы мастдайку вроде бубунты или красношапки).
Последний раз редактировалось Eddy_Em Пт мар 26, 2021 12:29:21, всего редактировалось 3 раза.
Re: STM32 и USB (практика)
Круто, спасибо, буду вдохновляться. Очень удобно что-то делать, если есть под рукой рабочий пример.Мои реализации CDC и Custom HID (работает с USB HID Demonstrator)
Я же за ночь добился того, что можно с хоста (через HID Demonstrator пробовал) управлять светодиодом. Код получается вполне компактным, как и прошивка (2116 Кб). Теперь надо переходить к CDC.
Спойлер
Код: Выделить всё
#include <clock.h>
#include <exti.h>
#include <iopins.h>
#include <pinlist.h>
#include <usb.h>
using namespace Zhele;
using namespace Zhele::Clock;
using namespace Zhele::IO;
using namespace Zhele::Usb;
using Report = HidReport<
0x06, 0x00, 0xff, // USAGE_PAGE (Generic Desktop)
0x09, 0x01, // USAGE (Vendor Usage 1)
0xa1, 0x01, // COLLECTION (Application)
0x85, 0x01, // REPORT_ID (1)
0x09, 0x01, // USAGE (Vendor Usage 1)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x75, 0x08, // REPORT_SIZE (8)
0x95, 0x01, // REPORT_COUNT (1)
0xb1, 0x82, // FEATURE (Data,Var,Abs,Vol)
0x85, 0x01, // REPORT_ID (1)
0x09, 0x01, // USAGE (Vendor Usage 1)
0x91, 0x82, // OUTPUT (Data,Var,Abs,Vol)
0xc0 // END_COLLECTION
>;
using HidDesc = HidDescriptor<0x1001, Report>;
using LedsControlEpBase = OutEndpointBase<1, EndpointType::Interrupt, 4, 32>;
using EpInitializer = EndpointsInitializer<DefaultEp0, LedsControlEpBase>;
using Ep0 = EpInitializer::ExtendEndpoint<DefaultEp0>;
using LedsControlEp = EpInitializer::ExtendEndpoint<LedsControlEpBase>;
using Hid = HidInterface<0, 0, 0, 0, HidDesc, LedsControlEp>;
using Config = HidConfiguration<0, 250, false, false, Report, Hid>;
using MyDevice = Device<0x0200, DeviceClass::InterfaceSpecified, 0, 0, 0x0483, 0x5711, 0, Ep0, Config>;
using Led = IO::Pc6; // Use Pc13 for BluePill.
void ConfigureClock();
void ConfigureLeds();
int main()
{
ConfigureClock();
ConfigureLeds();
Zhele::IO::Porta::Enable();
MyDevice::Enable();
for(;;)
{
}
}
void ConfigureClock()
{
PllClock::SelectClockSource(PllClock::ClockSource::Internal);
PllClock::SetMultiplier(12);
PllClock::SetDivider(2);
ApbClock::SetPrescaler(ApbClock::Div1);
SysClock::SelectClockSource(SysClock::Pll);
Zhele::Clock::Hsi48Clock::Enable();
Zhele::Clock::SysCfgCompClock::Enable();
}
void ConfigureLeds()
{
Led::Port::Enable();
Led::SetConfiguration<Led::Configuration::Out>();
Led::SetDriverType<Led::DriverType::PushPull>();
Led::Set();
}
template<>
void LedsControlEp::Handler()
{
LedsControlEp::ClearCtrRx();
uint8_t* buffer = reinterpret_cast<uint8_t*>(LedsControlEp::Buffer);
bool needSet = buffer[1] != 0;
switch(buffer[0])
{
case 1:
needSet ? Led::Set() : Led::Clear();
break;
}
LedsControlEp::SetRxStatus(EndpointStatus::Valid);
}
extern "C" void USB_IRQHandler()
{
// Sorry, but you must write device`s CommonHandler call by yourself.
MyDevice::CommonHandler();
}
- VladislavS
- Собутыльник Кота
- Сообщения: 2562
- Зарегистрирован: Вт май 01, 2018 19:44:47
Re: STM32 и USB (практика)
[uquote="azhel12",url="/forum/viewtopic.php?p=4004394#p4004394"]Код получается вполне компактным, как и прошивка (2116 Кб).[/uquote]У меня HID на один диод и кнопку на F072 получается вот такЭто с полной реализацией USB Device, строковыми дескрипторами, HID_REPORT на 5 REPORT_ID. Задача ужиматься не стояла. В принципе, ещё поджать есть куда.
Код: Выделить всё
C:/CPP/GNU Tools ARM Embedded/10-2020-q4-major/bin/arm-none-eabi-size Bin\Release/F072-HID.elf
text data bss dec hex filename
2072 8 96 2176 880 Bin\Release/F072-HID.elf- COKPOWEHEU
- Говорящий с текстолитом
- Сообщения: 1525
- Зарегистрирован: Чт июн 10, 2010 20:11:19
Re: STM32 и USB (практика)
В таком случае вам ни RTS/CTS/DTR биты не нужны, ни interrupt endpoint. Но они не нужны ВАМ. Не надо говорить, что они не нужны никому и никогда.Ну так мой CDC предназначен для организации "общения" с МК.
Ну и опять же переходник на COM-порт может быть побочной фичей типа "ноги свободные остались, почему бы и нет".
На Debian тоже какая-то гадость его занимает. Но я вылечил это проще: выставил class/subclass/protocol в 2/2/0 вместо 2/2/1. Оно все равно отображается как /dev/ttyACM, но посторонние программы не лезут.Я даже не CDC использую, т.к. мне не нравится /dev/ttyACMx в именовании + на мастдайках вроде бубунты по дефолту запущен modemd, который ACM пытается перехватить на себя и занимает порт.
Хотя ваш вариант тоже интересный, надо будет его поковырять.
Я тут недавно читал на него документацию, так там чего только нет! Ладно клавомыши, это все привыкли. Но там есть джойстик для танка и подводной лодки, есть индикатор активности жесткого диска и фиг поймешь чего еще. В общем-то всем рекомендую ознакомиться если не для практического использования, то хотя бы для поднятия настроения.Вообще не представляю себе, зачем кому-то может понадобится HID, если только он не изготавливает кастомные клавы-мыши-джойстики.
Ну и не стоит забывать про совсем нестандартные устройства, которым много данных не надо, но и писать ядерный драйвер лень. Я, например, пару лет назад делал таким способом переходник с научного вольтметра е-24 (он по COM-порту работает, да еще довольно заковыристым способом) на USB. Правда, делал на ATmega8. Почему бы и нет: скорости там нулевые, а кроссплатформенный драйвер писать все еще лень. А так оно работает себе потихоньку, никому не мешает.
Хм, а у меня 2308 кБ для f103 и 2792 кБ для L151. Отсюда два вопроса: что в моем коде занимает столько места? И почему в коде для L151 оно занимает места еще больше? Хотя, конечно, сейчас я это ковырять не буду.Я же за ночь добился того, что можно с хоста (через HID Demonstrator пробовал) управлять светодиодом. Код получается вполне компактным, как и прошивка (2116Кб).
- VladislavS
- Собутыльник Кота
- Сообщения: 2562
- Зарегистрирован: Вт май 01, 2018 19:44:47
Re: STM32 и USB (практика)
[uquote="COKPOWEHEU",url="/forum/viewtopic.php?p=4004412#p4004412"]что в моем коде занимает столько места?[/uquote]
Код: Выделить всё
C_FLAGS := -ffunction-sections -fdata-sections -fno-exceptions -Wall
CPP_FLAGS := -ffunction-sections -fdata-sections -fno-exceptions -fno-rtti -Wall
AS_FLAGS = $(C_FLAGS)
LD_FLAGS := -Wl,--gc-sections -nostartfiles -specs=nano.specs -specs=nosys.specs- COKPOWEHEU
- Говорящий с текстолитом
- Сообщения: 1525
- Зарегистрирован: Чт июн 10, 2010 20:11:19
Re: STM32 и USB (практика)
VladislavS, если добавить ваши флаги бездумно, прошивка вырастает на 52 байта. Если немного пошаманить - уменьшается на 20 байт.
Так что, скорее код причесывать надо.
Но лень. Надо еще с прерываниями и изохронными точками разобраться.
Так что, скорее код причесывать надо.
Но лень. Надо еще с прерываниями и изохронными точками разобраться.
- VladislavS
- Собутыльник Кота
- Сообщения: 2562
- Зарегистрирован: Вт май 01, 2018 19:44:47
Re: STM32 и USB (практика)
[uquote="COKPOWEHEU",url="/forum/viewtopic.php?p=4004465#p4004465"]Так что, скорее код причесывать надо.[/uquote]Смотрел ваш код. И как-то само придумалось. Даже не знаю, почему раньше не пришло в голову. БылоМожно сделать вот так
Код: Выделить всё
// По SetAddres
USB_Addr = setup_packet.wValue;
// По EP0 CTR_TX
if( (USB->DADDR & USB_DADDR_ADD) != USB_Addr )
{
USB->DADDR = USB_DADDR_EF | USB_Addr;
}Код: Выделить всё
// По SetAddres
USB_Addr = USB_DADDR_EF | setup_packet.wValue;
// По EP0 CTR_TX
USB->DADDR = USB_Addr;- Eddy_Em
- Собутыльник Кота
- Сообщения: 2516
- Зарегистрирован: Пт июл 12, 2019 22:52:01
- Контактная информация:
Re: STM32 и USB (практика)
COKPOWEHEU, так ведь если сравнивать "чистый код", то функционала он никакого нести не будет. А для его проверки идет всякая обвязка (хоть даже просто эхо введенного), что уже немного раздувает код.
Я вот тоже когда почистил свой сниппет для PL2303 от всякого ненужного (типа UART и т.п.), бинарник на пару килобайт уменьшился.
Я вот тоже когда почистил свой сниппет для PL2303 от всякого ненужного (типа UART и т.п.), бинарник на пару килобайт уменьшился.
- VladislavS
- Собутыльник Кота
- Сообщения: 2562
- Зарегистрирован: Вт май 01, 2018 19:44:47
Re: STM32 и USB (практика)
[uquote="Eddy_Em",url="/forum/viewtopic.php?p=4004476#p4004476"]так ведь если сравнивать "чистый код"[/uquote]У меня в примерах для HID управление светодиодами и опрос кнопки. Для CDC эхо, управление светодиодом и отправка тестового слова по кнопке. Так что, не совсем голяк.
- COKPOWEHEU
- Говорящий с текстолитом
- Сообщения: 1525
- Зарегистрирован: Чт июн 10, 2010 20:11:19
Re: STM32 и USB (практика)
Вы имеете в виду писать USB->DADDR при каждом вызове ep0 IN? Не нравится мне эта идея. Не могу точно сформулировать почему, но не нравится.Можно сделать вот так
Я сравниваю свой код из статьи, который зажигает два светодиода и отсылает состояние кнопки.COKPOWEHEU, так ведь если сравнивать "чистый код", то функционала он никакого нести не будет.
Кстати, это одна из причин почему разница объема меня не пугает. Чтобы аргументированно издеваться над сторонниками Куба достаточно, что разница объема более чем пятикратная, а остальное можно списать на погрешность функционала, на забытые отладочные куски и прочее.
- VladislavS
- Собутыльник Кота
- Сообщения: 2562
- Зарегистрирован: Вт май 01, 2018 19:44:47
Re: STM32 и USB (практика)
[uquote="COKPOWEHEU",url="/forum/viewtopic.php?p=4004491#p4004491"]Не нравится мне эта идея. Не могу точно сформулировать почему, но не нравится.[/uquote]Читать каждый раз вам нравится, значит? А записать то же значение, которое там уже есть, нет? Проверено, работает хорошо. Получается быстрее и меньше кодаТак как от базы R2 потом и остальные переменные адресуются, то получаются расходы только одна LDR и одна STRH. Не забываем, что это прерывание, ту всё должно быть как выстрел.
Код: Выделить всё
//case 0x00: // EP0 CTR_TX
// STM32_USB_DEVICE::ApplyAdr();
LDR R2,??USB_IRQHandler_0+0x8
LDR R1,[R2, #+28]
STRH R1,[R0, #+12]- COKPOWEHEU
- Говорящий с текстолитом
- Сообщения: 1525
- Зарегистрирован: Чт июн 10, 2010 20:11:19
Re: STM32 и USB (практика)
Так оперативку же читать, а не регистр периферии. Мало ли что они там навесили на операцию записи. Быстрее было бы сделать для этой штуки отдельный обработчик, но это хуже по объему кода, я проверял.
- VladislavS
- Собутыльник Кота
- Сообщения: 2562
- Зарегистрирован: Вт май 01, 2018 19:44:47
Re: STM32 и USB (практика)
[uquote="COKPOWEHEU",url="/forum/viewtopic.php?p=4004561#p4004561"]Так оперативку же читать, а не регистр периферии.[/uquote]Это в моей реализации было оперативку, а в вашей как раз и оперативку, и периферию. Плюс битовые операции и сравнение.
[uquote="COKPOWEHEU",url="/forum/viewtopic.php?p=4004561#p4004561"]Мало ли что они там навесили на операцию записи.[/uquote]Ничего, я же говорю, проверено. Да и вызывается это только из ep0.
[uquote="COKPOWEHEU",url="/forum/viewtopic.php?p=4004561#p4004561"]Быстрее было бы сделать для этой штуки отдельный обработчик, но это хуже по объему кода, я проверял.[/uquote]Это как?
Я вообще не настаиваю, не хотите пользоваться, ваше дело. В моём коде это поселилось.
[uquote="COKPOWEHEU",url="/forum/viewtopic.php?p=4004561#p4004561"]Мало ли что они там навесили на операцию записи.[/uquote]Ничего, я же говорю, проверено. Да и вызывается это только из ep0.
[uquote="COKPOWEHEU",url="/forum/viewtopic.php?p=4004561#p4004561"]Быстрее было бы сделать для этой штуки отдельный обработчик, но это хуже по объему кода, я проверял.[/uquote]Это как?
Я вообще не настаиваю, не хотите пользоваться, ваше дело. В моём коде это поселилось.
- COKPOWEHEU
- Говорящий с текстолитом
- Сообщения: 1525
- Зарегистрирован: Чт июн 10, 2010 20:11:19
Re: STM32 и USB (практика)
Колбэк на ep0_in после ресета выставить в функцию, которая будет настраивать адрес и подменять себя на "нормальный" колбэк.Это как?
Код: Выделить всё
void ep0_addr(){
if( (USB->DADDR & USB_DADDR_ADD) != USB_Addr ){
USB->DADDR = USB_DADDR_EF | USB_Addr;
ep0_in_handler = ep0_in;
}
}
void ep0_in(){
...
}Да, вы правы, это надо исправить. Посмотрю сработает ли мой вариант с колбэками и не слишком ли он раздует код. Вроде бы терпимо получалось.Это в моей реализации было оперативку, а в вашей как раз и оперативку, и периферию. Плюс битовые операции и сравнение.
- VladislavS
- Собутыльник Кота
- Сообщения: 2562
- Зарегистрирован: Вт май 01, 2018 19:44:47
Re: STM32 и USB (практика)
Да, с подменой понятно. Но вызов колбэка по скорости скорее всего проиграет проверке значения USB_Addr. Да и лишнее это, тут нет узкого места. Вопрос чисто спортивный, ценой в 8 байт размера прошивки в моём случае.


