73 lines
1.9 KiB
C
73 lines
1.9 KiB
C
/**
|
|
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
|
|
*
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include "pico/stdlib.h"
|
|
#include "hardware/timer.h"
|
|
#include "hardware/irq.h"
|
|
|
|
/// \tag::get_time[]
|
|
// Simplest form of getting 64 bit time from the timer.
|
|
// It isn't safe when called from 2 cores because of the latching
|
|
// so isn't implemented this way in the sdk
|
|
static uint64_t get_time(void) {
|
|
// Reading low latches the high value
|
|
uint32_t lo = timer_hw->timelr;
|
|
uint32_t hi = timer_hw->timehr;
|
|
return ((uint64_t) hi << 32u) | lo;
|
|
}
|
|
/// \end::get_time[]
|
|
|
|
/// \tag::alarm_standalone[]
|
|
// Use alarm 0
|
|
#define ALARM_NUM 0
|
|
#define ALARM_IRQ TIMER_IRQ_0
|
|
|
|
// Alarm interrupt handler
|
|
static volatile bool alarm_fired;
|
|
|
|
static void alarm_irq(void) {
|
|
// Clear the alarm irq
|
|
hw_clear_bits(&timer_hw->intr, 1u << ALARM_NUM);
|
|
|
|
// Assume alarm 0 has fired
|
|
printf("Alarm IRQ fired\n");
|
|
alarm_fired = true;
|
|
}
|
|
|
|
static void alarm_in_us(uint32_t delay_us) {
|
|
// Enable the interrupt for our alarm (the timer outputs 4 alarm irqs)
|
|
hw_set_bits(&timer_hw->inte, 1u << ALARM_NUM);
|
|
// Set irq handler for alarm irq
|
|
irq_set_exclusive_handler(ALARM_IRQ, alarm_irq);
|
|
// Enable the alarm irq
|
|
irq_set_enabled(ALARM_IRQ, true);
|
|
// Enable interrupt in block and at processor
|
|
|
|
// Alarm is only 32 bits so if trying to delay more
|
|
// than that need to be careful and keep track of the upper
|
|
// bits
|
|
uint64_t target = timer_hw->timerawl + delay_us;
|
|
|
|
// Write the lower 32 bits of the target time to the alarm which
|
|
// will arm it
|
|
timer_hw->alarm[ALARM_NUM] = (uint32_t) target;
|
|
}
|
|
|
|
int main() {
|
|
stdio_init_all();
|
|
printf("Timer lowlevel!\n");
|
|
|
|
// Set alarm every 2 seconds
|
|
while (1) {
|
|
alarm_fired = false;
|
|
alarm_in_us(1000000 * 2);
|
|
// Wait for alarm to fire
|
|
while (!alarm_fired);
|
|
}
|
|
}
|
|
|
|
/// \end::alarm_standalone[]
|