STM32L, USB, CDC, віртуальний COM-порт, початок, badembed
Спробуємо розібратися з реалізацієюUSB наSTM32L. Бібліотека відST просто жахлива. Ні, вона чудово працює, але на її прикладі розібратися зUSB навряд чи вийде. Вона написана дуже складно. А ось на прикладі відkeil (у них є свій приклад дляUSB) можна розібратися. Ось на такому трохи переробленому прикладі я і постараюся пояснити (хоч би для самого себе) як можна реалізувати USB на мікроконтролері.
У прикладі реалізується CDDC пристрій.
USB на ПК визначає підключення до шини якогось типу пристрою за появою підтяжки наDM абоDP.
- pull-up наD- на стороні девайсу - девайс каже, що вінLow-speed ;
- pull-up наD+ на стороні девайсу - девайс каже, що вінFull-speed абоHigh-speed (уточнюється в подальшому діалозі з хостом);
- обидва піна без підтяжок на боці девайсу - він відключений від шини, і хост з ним не працює;
Для підключення резистора доDP нам знадобиться модульSYSCFG і регістрPMC (крім того, бібліотеки периферії відST у файліstm32l1xx_syscfg.c є функціяSYSCFG_USBPuCmd, яка допоможе вам записати в цей регістр потрібні значення - вкл/викл підтяжку.
ІніціалізаціюUSB, для нашого мікроконтролера, розділимо на 3 частини.
- Налаштування частоти тактування мікроконтролера та увімк. тактування модулів периферії;
- Налаштування переривань відUSB;
- Ініціалізація самогоUSB модуля (налаштовуємо через відповідні регістри);
На початку треба налаштувати тактування самого мікроконтролера — для цього я зазвичай змінюю сам файлsystem_stm32l1xx.c (із стандартного проектуkeil дляSTM32 ). А точніше, функціюSetSysClock. ДляUSB нам необхідно, щоб післяPLLMUL була частота 96 МГц.

Якщо використовуємоHSI 16 МГц, треба вибрати коефіцієнт множення6. А потім, для того, щоб тактувати мікроконтролер відPLL вибрати, коефіцієнт розподілу3. Тоді на виході PLL , частота буде 32 МГц. При такій частоті, не забуваємо налаштувати пропуск такту під час читанняFLASH (вона може працювати максимум на частоті 24 МГц, і якщо пропуск не налаштувати програма буде просто виснути).
Тепер включаємо тактуванняUSB периферії таSYSCFG (для включення підтягуючого резистора - див. вище).
Тепер переходимо до налаштування переривань. У нашій програмі ми будемо використовувати лише вектор перериванняUSB_LP_IRQHandler.
Він був використаний у прикладі, і, якщо чесно, з іншими векторамиUSB переривань я не працював і не знаю як працювати. УReference Manual про них написано:
- USB low-priority interrupt (USB_LP_IRQHandler) — працює на всіхUSB подіях (коректна передача, USB reset і т.д.)
- USB high-priority interrupt (USB_HP_IRQHandler) — спрацьовує лише на події коректної передачі дляisochronous and double-buffer bulk і використовується для досягнення максимально можливої швидкості обміну.
- USB wakeup interrupt (USB_FS_WKUP_IRQHandler) — спрацьовує по прокиданню зSuspend mode.
Подальше налаштування відбуватиметься у перериванніUSB_LP_IRQHandler.
При спілкуванні з тією чи іншою кінцевою точкою викликається відповідна функція -USB_EndPoint0,USB_EndPoint1,USB_EndPoint2,USB_EndPoint3.
Саме в нульовій кінцевій точці реалізовані всі стандартні запитиUSB, запити специфічні дляCDC пристрою (вірт.COM -порту). При запиті до нульової точки віддається дескриптор пристрою (який необхідно заздалегідь прописати).
Друга та третя кінцева точка викликаються при прийомі та передачі даних відповідно. Точніше на передачу кінцева точка викликається постійно з якоюсь періодичністю, просто, грубо кажучи, передається нуль байт (можете подивитися у налагоджувачі - постійне влучення в функцію USB_EndPoint3 ). А в кінцеву точку на прийом потрапляємо лише коли прийшли дані з ПК.
Перша кінцева точка дляCDC пристрою використовується для налаштувань параметрів самогоCOM -порту (хоча не впевнений, я вже забув - розбирався давно).
Проект - USB_CDC - для скачування (проект зробленийkeil, заархівований 7Zip). Драйвер дляПК я брав відST, його можна завантажити або на сайтіST або завантажити - stsw-stm32102.