Как повторно включить USB-контроллер 32u4 после спящего режима?

У меня возникла проблема с моим 32u4: я не могу подключить его к компьютеру после выхода из спящего режима!

Итак, у меня есть Arduino Pro Micro с 32u4, и я также разрабатываю проект с автономным 32u4 (я использую Pro Micro в качестве тестовой платформы, прежде чем приступить к созданию своего проекта). Это устройство с батарейным питанием и плавным запуском, поэтому мне нужно, чтобы энергопотребление было минимальным (отсюда и спящие режимы).

После изучения регистров и ознакомления с некоторыми двоичными файлами перевод чипа в спящий режим оказался довольно простым, однако я не могу заставить внутренний USB-интерфейс 32u4 «возобновить пробуждение» или повторно подключиться к компьютеру. Я прикрепил свой код ниже. Я также протестировал этот код на своем Arduino Nano, и он работает отлично, однако с добавленными функциями USB 32u4 я не могу заставить его повторно подключиться к компьютеру, и мне приходится перезагружать чип миллион раз, чтобы IDE наконец заработала. распознайте его и загрузите в него что-нибудь еще.

Вот мой прекрасный код ниже. Все это происходит при запуске, переходе в режим сна, а когда прерывание на выводе 2 переходит в низкий уровень, микросхема снова включается и запускает мигающий скетч. Он засыпает, просыпается и запускает скетч, но он никогда не подключится к моему компьютеру, пока я не выполню аппаратный сброс.

int btn1Pin = 2;
int led1 = 9;

// это «стандартные» конфигурации регистров
byte _SMCR = 0; // отключаем спящий режим
byte _ADCSRA = 0b10000111; // повторно включаем АЦП

int interval = 500;
int ledState = true;
unsigned long ct1 = 0;
unsigned long pt1 = 0;

void setup()
{
  pinMode(led1, OUTPUT);
  attachInterrupt(digitalPinToInterrupt(btn1Pin), wakeUp, FALLING);  
  sleep();
}

void loop()
{
  ct1 = millis(); // моргаем что-нибудь, чтобы я знал, что ты работаешь
  if (ct1 - pt1 >= interval)
   {
     digitalWrite(led1, ledState);
     ledState = !ledState;
     pt1 = ct1;
   }
}

void wakeUp()
{
  SMCR = _SMCR; // отключаем спящий режим
  ADCSRA = _ADCSRA; // повторно включаем АЦП
}

void sleep()
{
  ADCSRA &= ~(1 << 7); // отключаем АЦП
  SMCR |= ( 1<<2 );    // режим выключения
  SMCR |= 1;           // включаем сон
  __asm__ __volatile__("sleep"); // гипнотизер щелкает пальцами, чип остыл!
}

В мозгу Эй-Джея (дополнительные исследования): Информационная таблица 32u4 для быстрого ознакомления

Я добавил быстрое включение светодиода в ISR WakeUp(), чтобы убедиться, что он действительно выполняется, и это действительно так.

Описание регистра USBCON (стр. 267 - 21.13.1) утверждает, что очистка бита 7 отключает и сбрасывает контроллер USB. Я попробовал еще одну итерацию кода, где в Sleep() я очистил бит 7, надеясь, что это сбросит контроллер, а в WakeUp() я установил бит, чтобы снова включить его после сброса, но это не сработало. На самом деле, это доставило мне большие трудности при попытке перепрограммирования (хотя я ЗНАЮ, что ISR WakeUp() выполняется и бит нужно было сбросить).

После некоторого чтения я увидел (Страница 262 - 21.7.2) сообщение о том, что в режиме пониженного энергопотребления (спящий режим, который я использую), "генератор останавливается и останавливает все тактовые сигналы (ЦП и периферийные устройства). USB-контроллер «просыпается». вверх', когда:

  • срабатывает прерывание WAKEUPI
  • срабатывает прерывание VBUSTI."

Хорошо, это имеет смысл, в режиме отключения питания USB-контроллер останавливается из-за отсутствия генератора, круто! Я понимаю, что это означает, что мне нужно вызвать одно из этих прерываний, чтобы повторно включить контроллер USB. Итак, я поискал первое прерывание «WAKEUPI», и оказалось, что этот бит устанавливается аппаратно (стр. 282). Я предполагаю, что это означает, что вы подключаете USB-кабель? Я написал скетч для чтения этого регистра, и он вернул 00010000, поэтому я предполагаю, что приведенное выше утверждение верно. В нем также говорится, что настройка с помощью программного обеспечения не имеет никакого эффекта, поэтому я оставил это, чтобы изучить следующее прерывание, VBUSTI, которое, по-видимому, является частью автоматического обнаружения подключения USB на основе панели VBUS. Возможно, здесь нужно что-то изменить, но я не могу сказать.

На странице 266 - 21.12 рассказывается о программных режимах работы USB, а последняя — «Возобновление работы интерфейса USB». Четыре пункта, которые помогут проснуться, таковы:

  • Включить ФАПЧ
  • Подождать блокировку PLL
  • Разморозить часы USB
  • Очистить информацию о резюме

Я попытался сделать все вышеперечисленное, добавив этот код в ISR WakeUp(). Это все равно не сработало :(. Я знаю, что это жестоко, и ISR должны быть как можно короче, но я все равно попробовал.

  PLLCSR = _PLLCSR; // включаем тактовую частоту ФАПЧ
  var = bitRead(PLLCSR, 0);   
  while (var != 1) {} // ждем, пока часы зафиксируются

  USBCON = _USBCON; // размораживаем часы USB
  UDINT = 0; // очищаем флаг возобновления

Может быть, я все это усложняю, не знаю! Я не могу заставить эту штуку снова подключиться.

, 👍1


1 ответ


Лучший ответ:

3

Вы слишком сильно к себе относитесь.

Существует способ перезапустить USB, но он работает только в том случае, если USB был правильно остановлен, а метод, который должен это сделать, пуст.

Это небольшой набросок, который работает на моем Леонардо:

#include <LowPower.h>

void setup() {      
}

void loop() {
    USBCON = 0;
    LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF);     

    USBDevice.attach();

    pinMode(13, OUTPUT);
    digitalWrite(13, HIGH);

    delay(10000);
    digitalWrite(13, LOW);
}

Он отключает USB (USBCON = 0;), переходит в режим ожидания на 8 секунд, затем снова запускает USB с нуля (USBDevice.attach();). Через 10 секунд он снова засыпает.

На компьютере вы получаете (в Linux):

[1242489.000014] usb 2-1.5.2: Product: USB IO Board
[1242489.000015] usb 2-1.5.2: Manufacturer: Arduino LLC
[1242489.000316] cdc_acm 2-1.5.2:1.0: ttyACM0: USB ACM device
[1242498.631563] usb 2-1.5.2: USB disconnect, device number 69
[1242507.068078] usb 2-1.5.2: new full-speed USB device number 70 using ehci-pci
[1242507.199628] usb 2-1.5.2: New USB device found, idVendor=2341, idProduct=0036
[1242507.199630] usb 2-1.5.2: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[1242507.199631] usb 2-1.5.2: Product: USB IO Board
[1242507.199633] usb 2-1.5.2: Manufacturer: Arduino LLC
[1242507.200256] cdc_acm 2-1.5.2:1.0: ttyACM0: USB ACM device
[1242517.063425] usb 2-1.5.2: USB disconnect, device number 70
[1242525.495729] usb 2-1.5.2: new full-speed USB device number 71 using ehci-pci
[1242525.627634] usb 2-1.5.2: New USB device found, idVendor=2341, idProduct=0036
.... etc ....
,

Сначала я пытался не использовать библиотеки, но забыл, что могу проверить их, чтобы увидеть, что они делают. Я очень ценю это, я определенно потрачу некоторое время на изучение этого., @HavocRC

USBdevice.attach находится в ядре, а не в библиотеке., @Majenko

Я говорил о малой мощности, лол. И действительно? Я этого не осознавал, я предполагал, что это часть малой мощности., @HavocRC

Я просто выразил это [ USBDevice.attach(); ] в мой исходный код в WakeUp ISR, USBCON = 0 в моем Sleep(), и все работает отлично!, @HavocRC

Я использовал низкую мощность только для сна, потому что это было удобно., @Majenko