Skip to content

Commit 8fd8e7d

Browse files
committed
Add cycle counter driver and test app
Also adds a helper function for SuccessU64 syscall return values
1 parent e5c540b commit 8fd8e7d

File tree

7 files changed

+122
-0
lines changed

7 files changed

+122
-0
lines changed

examples/tests/cycle_count/Makefile

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# Makefile for user application
2+
3+
# Specify this directory relative to the current application.
4+
TOCK_USERLAND_BASE_DIR = ../../..
5+
6+
# Which files to compile.
7+
C_SRCS := $(wildcard *.c)
8+
9+
# Include userland master makefile. Contains rules and flags for actually
10+
# building the application.
11+
include $(TOCK_USERLAND_BASE_DIR)/AppMakefile.mk

examples/tests/cycle_count/README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Test `cycle_count`
2+
====================
3+
4+
This tests the cycle counter capsule.
5+
It will print the number of cycles required to toggle an LED.

examples/tests/cycle_count/main.c

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
#include <stdio.h>
2+
3+
#include <cycle_counter.h>
4+
#include <led.h>
5+
#include <tock.h>
6+
7+
int main(void) {
8+
uint64_t cycles = 0;
9+
10+
int rc = cycle_counter_reset();
11+
if (rc == RETURNCODE_ENOSUPPORT) {
12+
printf("Cycle counter not available\n");
13+
} else if (rc == RETURNCODE_ERESERVE) {
14+
printf("Cycle counter claimed by another app\n");
15+
} else if (rc != 0) {
16+
printf("Cycle counter: other error: %d\n", rc);
17+
}
18+
19+
if (rc != 0) {
20+
return 0;
21+
}
22+
23+
cycle_counter_start();
24+
led_toggle(0);
25+
cycle_counter_stop();
26+
cycle_counter_read(&cycles);
27+
printf("cycles to toggle led first time: %lld\n", cycles);
28+
29+
cycle_counter_reset();
30+
cycle_counter_start();
31+
led_toggle(0);
32+
cycle_counter_stop();
33+
cycle_counter_read(&cycles);
34+
printf("cycles to toggle led second time: %lld\n", cycles);
35+
return 0;
36+
}

libtock/cycle_counter.c

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
#include "cycle_counter.h"
2+
3+
bool cycle_counter_exists(void) {
4+
return driver_exists(DRIVER_NUM_CYCLE_COUNTER);
5+
}
6+
7+
// Start the cycle counter
8+
int cycle_counter_start(void) {
9+
syscall_return_t rval = command(DRIVER_NUM_CYCLE_COUNTER, 1, 0, 0);
10+
return tock_command_return_novalue_to_returncode(rval);
11+
}
12+
13+
// Get the current cycle count
14+
int cycle_counter_read(uint64_t* count) {
15+
syscall_return_t rval = command(DRIVER_NUM_CYCLE_COUNTER, 2, 0, 0);
16+
return tock_command_return_u64_to_returncode(rval, (uint64_t*) count);
17+
}
18+
19+
// Reset the cycle counter
20+
int cycle_counter_reset(void) {
21+
syscall_return_t rval = command(DRIVER_NUM_CYCLE_COUNTER, 3, 0, 0);
22+
return tock_command_return_novalue_to_returncode(rval);
23+
}
24+
25+
// Stop the cycle counter
26+
int cycle_counter_stop(void) {
27+
syscall_return_t rval = command(DRIVER_NUM_CYCLE_COUNTER, 4, 0, 0);
28+
return tock_command_return_novalue_to_returncode(rval);
29+
}

libtock/cycle_counter.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#pragma once
2+
3+
#include "tock.h"
4+
5+
#ifdef __cplusplus
6+
extern "C" {
7+
#endif
8+
9+
#define DRIVER_NUM_CYCLE_COUNTER 0x00090008
10+
11+
bool cycle_counter_exists(void);
12+
int cycle_counter_start(void);
13+
int cycle_counter_stop(void);
14+
int cycle_counter_reset(void);
15+
int cycle_counter_read(uint64_t *count);
16+
17+
#ifdef __cplusplus
18+
}
19+
#endif

libtock/tock.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,21 @@ int tock_command_return_u32_to_returncode(syscall_return_t command_return, uint3
6666
}
6767
}
6868

69+
int tock_command_return_u64_to_returncode(syscall_return_t command_return, uint64_t* val) {
70+
if (command_return.type == TOCK_SYSCALL_SUCCESS_U64) {
71+
uint32_t upper = command_return.data[1];
72+
uint32_t lower = command_return.data[0];
73+
*val = ((uint64_t)upper << 32) | lower;
74+
return RETURNCODE_SUCCESS;
75+
} else if (command_return.type == TOCK_SYSCALL_FAILURE) {
76+
return tock_status_to_returncode(command_return.data[0]);
77+
} else {
78+
// The remaining SyscallReturn variants must never happen if using this
79+
// function. We return `EBADRVAL` to signal an unexpected return variant.
80+
return RETURNCODE_EBADRVAL;
81+
}
82+
}
83+
6984
int tock_subscribe_return_to_returncode(subscribe_return_t subscribe_return) {
7085
// If the subscribe was successful, easily return SUCCESS.
7186
if (subscribe_return.success) {

libtock/tock.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,13 @@ int tock_command_return_novalue_to_returncode(syscall_return_t);
152152
// variants.
153153
int tock_command_return_u32_to_returncode(syscall_return_t, uint32_t*);
154154

155+
// Convert a `syscall_return_t` with two u32s to a `returncode_t`.
156+
//
157+
// This expects exactly two u32s to be returned (i.e. the only success case is
158+
// `TOCK_SYSCALL_SUCCESS_U64`). Do not use with other expected SyscallReturn
159+
// variants.
160+
int tock_command_return_u64_to_returncode(syscall_return_t, uint64_t*);
161+
155162
// Convert a `subscribe_return_t` to a `returncode_t`.
156163
int tock_subscribe_return_to_returncode(subscribe_return_t);
157164

0 commit comments

Comments
 (0)