Der WFI-Aufruf funktioniert, er empfängt fast unmittelbar nach dem Aufruf einen Interrupt, der dazu führt, dass der WFI-Aufruf aufhört zu blockieren, und dann wird die Ausführung in der nächsten Zeile fortgesetzt.
Sie könnten alles unter // Go to sleep
sicher entfernen, wodurch die Hauptfunktion zurückkehren würde. Der AON-Timer würde immer noch seinen Rückruf ausführen. Es gibt jedoch einige mögliche Nachteile dieses Ansatzes:
Das würde SAMB11 nicht in einen niedrigeren Leistungsmodus wechseln.
Dies entfernt Ihre While-Schleife am Ende des Main. In seinem aktuellen Status wird die while-Schleife nicht benötigt, aber Sie möchten möglicherweise später Code hinzufügen.
Hier ist ein Beispiel, das den AON konfiguriert, den SAMB11 so konfiguriert, dass er Low-Power-Modi verwendet, und dann Schleifen, die auf Plattform- und/oder BLE-Ereignisse warten. Momentan gibt es keine Ereignisse für den Empfang der Schleife. Wenn Sie möchten, dass die Schleife Ereignisse empfängt, können Sie den AON-Rückruf ändern, um ein Ereignis mit der Funktion at_ble_event_user_defined_post
zu posten oder main()
ändern, um das BLE-Modul vor dem Eintritt in die Schleife zu konfigurieren.
Verwenden Sie den ASF-Assistenten, um eines der BLE-Module zu Ihrem Projekt hinzuzufügen, um dieses Beispiel zu kompilieren.
#include <asf.h>
#include "platform.h"
// Configure LED
static void configure_gpio_pins(void)
{
struct gpio_config config_gpio_pin;
gpio_get_config_defaults(&config_gpio_pin);
config_gpio_pin.direction = GPIO_PIN_DIR_OUTPUT;
gpio_pin_set_config(LED_0_PIN, &config_gpio_pin);
gpio_pin_set_output_level(LED_0_PIN, LED_0_INACTIVE);
}
// Callback Func to toggle LED
static bool led_is_on = false;
static void aon_sleep_timer_callback(void)
{
configure_gpio_pins();
if(led_is_on) {
gpio_pin_set_output_level(LED_0_PIN, LED_0_INACTIVE);
led_is_on = false;
} else {
gpio_pin_set_output_level(LED_0_PIN, LED_0_ACTIVE);
led_is_on = true;
}
}
// Configure Timer to fire periodically
static void configure_aon_sleep_timer(void)
{
struct aon_sleep_timer_config config_aon_sleep_timer;
aon_sleep_timer_get_config_defaults(&config_aon_sleep_timer);
config_aon_sleep_timer.counter = 32000; // Wait about 1 sec
config_aon_sleep_timer.mode = AON_SLEEP_TIMER_RELOAD_MODE;
aon_sleep_timer_init(&config_aon_sleep_timer);
}
// Configure Callback and enable Interrupt
static void configure_aon_sleep_timer_callback(void)
{
aon_sleep_timer_register_callback(aon_sleep_timer_callback);
NVIC_EnableIRQ(AON_SLEEP_TIMER0_IRQn);
}
int main(void)
{
// Setup Clock
system_clock_config(CLOCK_RESOURCE_XO_26_MHZ, CLOCK_FREQ_26_MHZ);
plf_drv_status plf_status;
if((plf_status = platform_driver_init()) == STATUS_SUCCESS) {
// Setup LED and Timer
configure_gpio_pins();
configure_aon_sleep_timer();
configure_aon_sleep_timer_callback();
// wait for timer to be active
while(!aon_sleep_timer_sleep_timer_active());
// Go to sleep
release_sleep_lock();
while(true) {
// Replace platform_event_wait with at_ble_event_get if you would like to read the received event.
plf_status = platform_event_wait(0);
}
}
}
WFI In Bezug auf das folgende Beispiel zeigt, wie die meisten der Interrupts deaktivieren und verwenden WFI main()
zu blockieren. Die LED wird jedes Mal umschalten, wenn ein Interrupt empfangen wird. Ich empfehle nicht, dies zu verwenden, da ich nicht sicher bin, warum diese Interrupts anfänglich aktiviert sind. Dies soll nur zeigen, wie WFI auf einem SAMB11 blockieren kann.
#include <asf.h>
#include "platform.h"
// Configure LED
static void configure_gpio_pins(void)
{
struct gpio_config config_gpio_pin;
gpio_get_config_defaults(&config_gpio_pin);
config_gpio_pin.direction = GPIO_PIN_DIR_OUTPUT;
gpio_pin_set_config(LED_0_PIN, &config_gpio_pin);
gpio_pin_set_output_level(LED_0_PIN, LED_0_INACTIVE);
}
// Callback Func to toggle LED
static bool led_is_on = false;
static void toggle_led(void)
{
configure_gpio_pins();
if(led_is_on) {
gpio_pin_set_output_level(LED_0_PIN, LED_0_INACTIVE);
led_is_on = false;
} else {
gpio_pin_set_output_level(LED_0_PIN, LED_0_ACTIVE);
led_is_on = true;
}
}
int main(void)
{
// Setup Clock
system_clock_config(CLOCK_RESOURCE_XO_26_MHZ, CLOCK_FREQ_26_MHZ);
// Clear all interrupts.
NVIC->ICER[0] = 0xFFFFFFFF;
// During testing, interrupts were received about once per second; stopped receiving interrupts (LED stopped flashing) after about 2 minutes.
int loop_count = 0;
while(true) {
__WFI();
toggle_led();
}
}
Was macht 'aon_sleep_timer_sleep_timer_active()' - fragt es nur ein Statusregister ab?Es wäre praktisch, zwei verschiedene LEDs zu verwenden, damit Sie erkennen können, ob Sie den Interrupt sofort oder aufgrund eines anderen Ereignisses durchbrechen. – Notlikethat