Schlafen Sie auf Arm Cortex

Ich versuche, einen Cortex m4-Prozessor (m3 mit DSP-Erweiterungen) für etwas weniger als eine Sekunde in den Ruhezustand zu versetzen. Ich möchte in der Lage sein, ihm zu sagen, dass er schlafen soll, und eine Sekunde später oder wenn ein Knopf gedrückt wird, genau dort weitermachen, wo ich aufgehört habe. Ich habe im Referenzhandbuch nachgesehen und die VLPS- oder LLS-Modi sehen so aus, als würden sie meinen Anforderungen entsprechen. Idealerweise hätte ich gerne eine verherrlichte Verzögerungsfunktion, damit es für eine Sekunde schläft. Ich weiß nicht, wie ich anfangen soll, in diesen Modus zu wechseln oder wie ich das NVIC programmieren soll. Ich verwende C auf Bare-Metal.

Jede Hilfe wäre sehr willkommen.

Hier ist der Code:

#include "IntervalTimer.h"

//The following is where the SLEEPDEEP flag is at
#define SCR         (*((volatile unsigned long *) 0xE000ED10))

volatile uint32_t timerCounter0;
boolean printNow = false;

void timerCallback0() {
  timerCounter0++;
  printNow = true;
}

void setup() {
  SCR = SCR | 0x04;    //Set SLEEPDEEP
  Serial.begin(true);
  IntervalTimer timer0;
  timer0.begin(timerCallback0, 1000000);
}

void loop() {
  if (printNow) {
    Serial.println(timerCounter0);
    printNow = false;
    asm("wfi\n");
  }
}

Antworten (3)

Sie zählen viele Perioden eines ziemlich kurzen Timers, bei dessen Ablauf Sie aufwachen müssen. Um maximale Energieeinsparungen zu erzielen, müssen Sie das Timing vollständig in die Hardware stecken, sodass Sie nur am Ende des gewünschten Zeitraums oder zumindest ziemlich selten einen Interrupt generieren. Sie sollten wahrscheinlich einen größeren Wert im Timer-Register und möglicherweise einen preskalaren Teiler verwenden. (Selbst wenn Sie nur ein paar Mal pro Sekunde aufwachen und daher nicht viel Strom verschwenden, wird es dadurch mühsam, den Stromverbrauch zu messen, es sei denn, Sie verwenden ein Oszilloskop, um über einen Vorwiderstand zu messen.)

Aber selbst dann würden Sie wahrscheinlich immer noch mit einem schnellen PLL-Takt arbeiten, der viel Strom verbraucht. Um mehr Strom zu sparen, sollten Sie also zu einer Taktquelle mit geringem Stromverbrauch wechseln, z. B. zu einem internen oder externen Backup-Takt im KHz-Bereich, oder zumindest die PLL deaktivieren und möglicherweise einen systemweiten Taktvorskalierungsteiler hochdrehen.

Und Sie haben wahrscheinlich auch viele Teile des Chips eingeschaltet und getaktet, die im Ruhemodus nicht benötigt werden - wahrscheinlich möchten Sie alles außer GPIO, Interrupt-Controller, Zählermodul und RAM ausschalten und enttakten.

Darüber hinaus müssen Sie Ihr Schaltungsdesign auf alle Fälle prüfen, in denen Sie ein Signal gegen einen Pullup- oder Pulldown-Widerstand treiben oder sogar einen digitalen Eingang in der Nähe eines logischen Übergangs schweben lassen.

Ein System in den Mikroampere-Standby-Modus zu versetzen, kann ein kompliziertes Projekt sein, da Sie eine Leistungsleckage nach der anderen eliminieren. Achten Sie auch auf Debugger-, serielle, USB- usw. Verbindungen - nicht nur als potenzielle Lasten, sondern auch als potenzielle Stealth-Stromquellen für das System, um Strom zu erhalten, während das, was Sie messen, umgangen wird (ja, Sie können Energie von Datenpins erhalten).

Ich bin mir nicht sicher, welche MCU Sie genau verwenden, also habe ich im STM32F4- Referenzhandbuch nachgesehen , mit dem ich am besten vertraut bin. Da die Schlafmodi vom ARM-Kern implementiert werden, sollte es ähnlich wie bei jeder anderen Cortex-M4-MCU sein. Abschnitt 5.3.3 bespricht das Eintreten/Beenden des Schlafmodus (lesen Sie es für Details).

Um in den Schlafmodus zu wechseln:

Der Schlafmodus wird durch Ausführen der Anweisungen WFI (Warten auf Unterbrechung) oder WFE (Warten auf Ereignis) betreten.

Abhängig vom Wert eines Registers wird der Schlafmodus sofort betreten oder erst nachdem er die ISR mit der niedrigsten Priorität verlassen hat.

Um nach 1 Sekunde zu beenden, müssen Sie einen Timer einrichten, der nach 1 Sekunde eine ISR auslöst. (Da dies von der MCU-Implementierung abhängt, überspringe ich die Details für den STM32F4.) Wenn mit WFI in den Ruhemodus gewechselt wurde, weckt dieser Interrupt (sowie jeder andere Interrupt) die MCU. Wenn Sie eine detailliertere Kontrolle darüber benötigen, was die MCU aufwecken soll, sollten Sie mit WFE schlafen und das Weckereignis einrichten (Abschnitt 10.2.3 des Handbuchs).

Ich habe die WFI-Anweisung im Code verwendet, um zu überprüfen, ob sie funktioniert, aber sie hat nichts bewirkt. Muss ich vorher einen Interrupt einrichten?
Ja, Sie müssen einen Timer einrichten, damit er nach einer Sekunde unterbricht. Wenn Sie keinen Effekt sehen, könnte es auch sein, dass Sie einen anderen Interrupt haben, der wiederholt ausgelöst wird und somit das Beenden des Ruhezustands erzwingt, direkt nachdem WFI aufgerufen wurde.
Ich habe die Beschreibung so bearbeitet, dass sie den von mir verwendeten Code enthält. Es funktioniert wie erwartet, aber die Leistungsaufnahme ist die gleiche. Irgendwelche Ideen?

Ich bin mir nicht sicher, ob es das ist, wonach Sie gesucht haben, aber ich werde es trotzdem versuchen.

sleep()Wenn Sie C verwenden, sollten Sie in der Lage sein, den Prozessor mit der Funktion von zu veranlassen, nichts zu tun (dh zu schlafen) <time.h>.

Erfrischer:

#include <time.h>

 int main() {
     int sleepms;
     sleep(sleepms); //Sleep for "sleepms" milliseconds
 }
Nein, sleep ist Teil von posix, nicht C. Die Frage betrifft die Bare-Metal-Entwicklung, und dies würde nur funktionieren, wenn es einen Scheduler oder eine Support-Bibliothek gibt, die ein sleep() so implementiert, dass der Kern letztendlich ausgesetzt (oder zumindest drastisch reduziert) wird die Uhr), wenn es keine anderen Aufgaben gibt, die es erfordern, dass sie aktiv ist.