Initial Release
This commit is contained in:
5
timer/CMakeLists.txt
Normal file
5
timer/CMakeLists.txt
Normal file
@@ -0,0 +1,5 @@
|
||||
if (NOT PICO_NO_HARDWARE)
|
||||
add_subdirectory(hello_timer)
|
||||
endif ()
|
||||
add_subdirectory(periodic_sampler)
|
||||
add_subdirectory(timer_lowlevel)
|
||||
12
timer/hello_timer/CMakeLists.txt
Normal file
12
timer/hello_timer/CMakeLists.txt
Normal file
@@ -0,0 +1,12 @@
|
||||
add_executable(hello_timer
|
||||
hello_timer.c
|
||||
)
|
||||
|
||||
# Pull in our (to be renamed) simple get you started dependencies
|
||||
target_link_libraries(hello_timer pico_stdlib)
|
||||
|
||||
# create map/bin/hex file etc.
|
||||
pico_add_extra_outputs(hello_timer)
|
||||
|
||||
# add url via pico_set_program_url
|
||||
example_auto_set_url(hello_timer)
|
||||
58
timer/hello_timer/hello_timer.c
Normal file
58
timer/hello_timer/hello_timer.c
Normal file
@@ -0,0 +1,58 @@
|
||||
/**
|
||||
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "pico/stdlib.h"
|
||||
|
||||
/// \tag::timer_example[]
|
||||
volatile bool timer_fired = false;
|
||||
|
||||
int64_t alarm_callback(alarm_id_t id, void *user_data) {
|
||||
printf("Timer %d fired!\n", (int) id);
|
||||
timer_fired = true;
|
||||
// Can return a value here in us to fire in the future
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool repeating_timer_callback(struct repeating_timer *t) {
|
||||
printf("Repeat at %lld\n", time_us_64());
|
||||
return true;
|
||||
}
|
||||
|
||||
int main() {
|
||||
stdio_init_all();
|
||||
printf("Hello Timer!\n");
|
||||
|
||||
// Call alarm_callback in 2 seconds
|
||||
add_alarm_in_ms(2000, alarm_callback, NULL, false);
|
||||
|
||||
// Wait for alarm callback to set timer_fired
|
||||
while (!timer_fired) {
|
||||
tight_loop_contents();
|
||||
}
|
||||
|
||||
// Create a repeating timer that calls repeating_timer_callback.
|
||||
// If the delay is > 0 then this is the delay between the previous callback ending and the next starting.
|
||||
// If the delay is negative (see below) then the next call to the callback will be exactly 500ms after the
|
||||
// start of the call to the last callback
|
||||
struct repeating_timer timer;
|
||||
add_repeating_timer_ms(500, repeating_timer_callback, NULL, &timer);
|
||||
sleep_ms(3000);
|
||||
bool cancelled = cancel_repeating_timer(&timer);
|
||||
printf("cancelled... %d\n", cancelled);
|
||||
sleep_ms(2000);
|
||||
|
||||
// Negative delay so means we will call repeating_timer_callback, and call it again
|
||||
// 500ms later regardless of how long the callback took to execute
|
||||
add_repeating_timer_ms(-500, repeating_timer_callback, NULL, &timer);
|
||||
sleep_ms(3000);
|
||||
cancelled = cancel_repeating_timer(&timer);
|
||||
printf("cancelled... %d\n", cancelled);
|
||||
sleep_ms(2000);
|
||||
printf("Done\n");
|
||||
return 0;
|
||||
}
|
||||
/// \end::timer_example[]
|
||||
14
timer/periodic_sampler/CMakeLists.txt
Normal file
14
timer/periodic_sampler/CMakeLists.txt
Normal file
@@ -0,0 +1,14 @@
|
||||
if (NOT PICO_TIME_NO_ALARM_SUPPORT)
|
||||
add_executable(periodic_sampler
|
||||
periodic_sampler.c
|
||||
)
|
||||
|
||||
# Pull in our (to be renamed) simple get you started dependencies
|
||||
target_link_libraries(periodic_sampler pico_stdlib)
|
||||
|
||||
# create map/bin/hex file etc.
|
||||
pico_add_extra_outputs(periodic_sampler)
|
||||
|
||||
# add url via pico_set_program_url
|
||||
example_auto_set_url(periodic_sampler)
|
||||
endif()
|
||||
82
timer/periodic_sampler/periodic_sampler.c
Normal file
82
timer/periodic_sampler/periodic_sampler.c
Normal file
@@ -0,0 +1,82 @@
|
||||
/**
|
||||
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "pico/stdlib.h"
|
||||
#include "pico/util/queue.h"
|
||||
|
||||
bool timer_callback(repeating_timer_t *rt);
|
||||
|
||||
queue_t sample_fifo;
|
||||
|
||||
// using struct as an example, but primitive types can be used too
|
||||
typedef struct element {
|
||||
uint value;
|
||||
} element_t;
|
||||
|
||||
const int FIFO_LENGTH = 32;
|
||||
|
||||
int main() {
|
||||
stdio_init_all();
|
||||
|
||||
int hz = 25;
|
||||
|
||||
queue_init(&sample_fifo, sizeof(element_t), FIFO_LENGTH);
|
||||
|
||||
repeating_timer_t timer;
|
||||
|
||||
// negative timeout means exact delay (rather than delay between callbacks)
|
||||
if (!add_repeating_timer_us(-1000000 / hz, timer_callback, NULL, &timer)) {
|
||||
printf("Failed to add timer\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// read some blocking
|
||||
|
||||
for (int i = 0; i < 10; i++) {
|
||||
element_t element;
|
||||
queue_remove_blocking(&sample_fifo, &element);
|
||||
printf("Got %d: %d\n", i, element.value);
|
||||
}
|
||||
|
||||
// now retrieve all that are available periodically (simulate polling)
|
||||
for (int i = 0; i < 10; i++) {
|
||||
int count = queue_get_level(&sample_fifo);
|
||||
if (count) {
|
||||
printf("Getting %d, %d:\n", i, count);
|
||||
for (; count > 0; count--) {
|
||||
element_t element;
|
||||
queue_remove_blocking(&sample_fifo, &element);
|
||||
printf(" got %d\n", element.value);
|
||||
}
|
||||
}
|
||||
sleep_us(5000000 / hz); // sleep for 5 times the sampling period
|
||||
}
|
||||
|
||||
cancel_repeating_timer(&timer);
|
||||
|
||||
// drain any remaining
|
||||
element_t element;
|
||||
while (queue_try_remove(&sample_fifo, &element)) {
|
||||
printf("Got remaining %d\n", element.value);
|
||||
}
|
||||
|
||||
queue_free(&sample_fifo);
|
||||
printf("Done\n");
|
||||
}
|
||||
|
||||
bool timer_callback(repeating_timer_t *rt) {
|
||||
static int v = 100;
|
||||
element_t element = {
|
||||
.value = v
|
||||
};
|
||||
v += 100;
|
||||
|
||||
if (!queue_try_add(&sample_fifo, &element)) {
|
||||
printf("FIFO was full\n");
|
||||
}
|
||||
return true; // keep repeating
|
||||
}
|
||||
15
timer/timer_lowlevel/CMakeLists.txt
Normal file
15
timer/timer_lowlevel/CMakeLists.txt
Normal file
@@ -0,0 +1,15 @@
|
||||
if (PICO_ON_DEVICE)
|
||||
add_executable(timer_lowlevel
|
||||
timer_lowlevel.c)
|
||||
|
||||
# Disable SDK alarm support for this lowlevel example
|
||||
set(PICO_TIME_DEFAULT_ALARM_POOL_DISABLED 1)
|
||||
|
||||
target_link_libraries(timer_lowlevel pico_stdlib)
|
||||
|
||||
# create map/bin/hex file etc.
|
||||
pico_add_extra_outputs(timer_lowlevel)
|
||||
|
||||
# add url via pico_set_program_url
|
||||
example_auto_set_url(timer_lowlevel)
|
||||
endif ()
|
||||
73
timer/timer_lowlevel/timer_lowlevel.c
Normal file
73
timer/timer_lowlevel/timer_lowlevel.c
Normal file
@@ -0,0 +1,73 @@
|
||||
/**
|
||||
* 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[]
|
||||
Reference in New Issue
Block a user