Skip to content

Commit 35d637e

Browse files
committed
samples: boards: TDK Robokit1 Sensor Sample
Provides a sample demonstrating the fast sensor on a tdk robokit1 used with and without RTIO. With RTIO the sample may be built with SPI_RTIO enabled or disabled to get a sense of the cost of a filler thread when SPI does not support RTIO as well. Signed-off-by: Tom Burdick <[email protected]>
1 parent c7f6d8b commit 35d637e

File tree

5 files changed

+268
-0
lines changed

5 files changed

+268
-0
lines changed
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# Copyright (c) 2022 Intel Corporation
2+
#
3+
# SPDX-License-Identifier: Apache-2.0
4+
#
5+
cmake_minimum_required(VERSION 3.20.0)
6+
7+
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
8+
project(tdk_robokit1)
9+
10+
target_include_directories(app PRIVATE $ENV{ZEPHYR_BASE}/drivers/sensor/icm42688)
11+
target_sources(app PRIVATE src/main.c)
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
.. _tdk_robokit1 sensors:
2+
3+
TDK Robokit1
4+
############
5+
6+
Overview
7+
********
8+
9+
This sample provides an example of how to read sensors data
10+
from the TDK RoboKit1 board using polling and RTIO.
11+
12+
This sample enables all sensors of TDK RoboKit1 board, and then
13+
periodically reads and displays data on the console from the following
14+
sensors:
15+
16+
- ICM42688: 6-Axis acceleration and angular velocity
17+
18+
Requirements
19+
************
20+
21+
The application requires a TDK RoboKit1 board connected to the PC
22+
through USB.
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
CONFIG_ARM_MPU=y # Seemingly not working
2+
CONFIG_FPU=n
3+
CONFIG_CBPRINTF_FP_SUPPORT=n
4+
CONFIG_ASSERT=y
5+
CONFIG_STACK_SENTINEL=y
6+
CONFIG_ENTROPY_GENERATOR=y
7+
CONFIG_STACK_CANARIES=y
8+
CONFIG_LOG=y # causes mpu fault?
9+
CONFIG_LOG_PRINTK=y
10+
CONFIG_LOG_MODE_DEFERRED=y
11+
CONFIG_SPI=y
12+
CONFIG_I2C=y
13+
CONFIG_GPIO=y
14+
CONFIG_LOG_PROCESS_THREAD_STACK_SIZE=8192
15+
CONFIG_MAIN_STACK_SIZE=2048
16+
CONFIG_ISR_STACK_SIZE=2048
17+
CONFIG_ICM42688_THREAD_STACK_SIZE=768
18+
19+
# config sensors
20+
CONFIG_DMA=y
21+
CONFIG_DMA_LOG_LEVEL_INF=y
22+
CONFIG_SENSOR=y
23+
CONFIG_SENSOR_LOG_LEVEL_DBG=y
24+
CONFIG_SPI_LOG_LEVEL_DBG=y
25+
CONFIG_ICM42688_RTIO=y
26+
CONFIG_RTIO=y
27+
CONFIG_SPI_SAM_DMA=y
28+
#CONFIG_RTIO_SUBMIT_SEM=n
29+
CONFIG_RTIO_CONSUME_SEM=y
30+
31+
32+
# SystemView Tracing
33+
CONFIG_TRACING=y
34+
CONFIG_TRACING_TIMER=y
35+
CONFIG_TRACING_SYSCALL=n
36+
CONFIG_SEGGER_SYSTEMVIEW=y
37+
CONFIG_SEGGER_SYSVIEW_RTT_BUFFER_SIZE=65536
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
sample:
2+
description: TDK RoboKit1 Test App for Sensors
3+
name: tdk_robokit1
4+
5+
tests:
6+
sample.boards.tdk_robokit1:
7+
platform_allow: tdk_robokit1
8+
tags: rtio sensor
Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
/*
2+
* Copyright (c) 2022 Intel Corporation
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#include <zephyr/kernel.h>
8+
#include <zephyr/drivers/sensor.h>
9+
#include <zephyr/rtio/rtio.h>
10+
#include <zephyr/rtio/rtio_executor_simple.h>
11+
12+
#include <stdint.h>
13+
#include <stdio.h>
14+
15+
#include <zephyr/logging/log.h>
16+
LOG_MODULE_REGISTER(TDK_ROBOKIT1, CONFIG_SENSOR_LOG_LEVEL);
17+
18+
/* Power of 2 number of stream buffers */
19+
#define N_BUFS 4
20+
21+
RTIO_EXECUTOR_SIMPLE_DEFINE(r_exec);
22+
23+
/* Show no over/under flows with a 4 buffer queue */
24+
RTIO_DEFINE(r4, (struct rtio_executor *)&r_exec, N_BUFS, N_BUFS);
25+
26+
/* Show over/underflows with a single buffer queue */
27+
RTIO_DEFINE(r1, (struct rtio_executor *)&r_exec, 1, 1);
28+
29+
#define FIFO_ITERS 4096
30+
31+
struct fifo_header {
32+
uint8_t int_status;
33+
uint16_t gyro_odr: 4;
34+
uint16_t accel_odr: 4;
35+
uint16_t gyro_fs: 3;
36+
uint16_t accel_fs: 3;
37+
uint16_t packet_format: 2;
38+
} __packed;
39+
40+
/* The fifo size (2048) bytes plus 3 for the header */
41+
#define ICM42688_FIFO_BUF_LEN 2051
42+
static uint8_t icm42688_fifo_bufs[N_BUFS][ICM42688_FIFO_BUF_LEN];
43+
44+
45+
void fifo_stream(const struct device *icm42688, struct rtio *r, uint32_t n_bufs)
46+
{
47+
struct rtio_iodev *iodev;
48+
struct rtio_sqe *sqe;
49+
50+
LOG_INF("FIFO with RTIO context %p, context size %u", r, sizeof(*r));
51+
52+
/* obtain reference the stream */
53+
(void)sensor_fifo_iodev(icm42688, &iodev);
54+
55+
LOG_INF("Setting up RX requests");
56+
57+
__ASSERT_NO_MSG(iodev != NULL);
58+
59+
/* Feed initial read requests */
60+
for (int i = 0; i < n_bufs; i++) {
61+
sqe = rtio_spsc_acquire(r->sq);
62+
rtio_sqe_prep_read(sqe, iodev, 0, &icm42688_fifo_bufs[i][0], ICM42688_FIFO_BUF_LEN,
63+
(void *)(uintptr_t)i);
64+
rtio_spsc_produce(r->sq);
65+
}
66+
67+
/* Submits requests */
68+
rtio_submit(r, 0);
69+
70+
/* Setup requests, starting stream */
71+
LOG_INF("Polling RX Requests");
72+
73+
/* Enable the fifo automatic triggering (via gpio) */
74+
sensor_fifo_start(icm42688);
75+
76+
uint32_t overflows = 0;
77+
78+
/* Now poll for ready fifo buffers for a little bit, at 32KHz sampling
79+
* and a 1024 buffer read with 16 bytes a sample, the fifo holds
80+
* 64 samples. At 32KHz it triggers every 2ms! this means
81+
* Every buffer has ~2ms to process or we lose the next sample.
82+
*
83+
* Every 8th buffer we busy wait just over 2ms to show how no data
84+
* is lost even with some variable latency involved. This could
85+
* come from data processing or attempting to transport the data
86+
* to another device.
87+
*
88+
* From the sensor a lack of buffer to read into is an underflow
89+
* and from the application perspective being unable to keep up
90+
* is an overflow.
91+
*/
92+
for (int i = 0; i < FIFO_ITERS; i++) {
93+
struct rtio_cqe *cqe = rtio_cqe_consume_block(r);
94+
int32_t result = cqe->result;
95+
uintptr_t buf_idx = (uintptr_t)cqe->userdata;
96+
uint8_t *buf = &icm42688_fifo_bufs[buf_idx][0];
97+
98+
rtio_spsc_release(r->cq);
99+
100+
/* The first byte is the interrupt status and can be
101+
* checked for a FIFO FULL signifying an overflow
102+
*/
103+
struct fifo_header *hdr = (void *)&buf[0];
104+
105+
if (hdr->int_status & BIT(1)) {
106+
overflows++;
107+
}
108+
109+
110+
if (i % 128 == 0) {
111+
printk("Slow mode on iteration %d, underflows (sensor overflows) %u, buf "
112+
"%lu, data int status %x, result %d\n",
113+
i, overflows, buf_idx, buf[0], result);
114+
k_busy_wait(4000);
115+
}
116+
117+
/* Now to recycle the buffer by putting it back in the queue */
118+
struct rtio_sqe *sqe = rtio_spsc_acquire(r->sq);
119+
120+
__ASSERT_NO_MSG(sqe != NULL);
121+
rtio_sqe_prep_read(sqe, iodev, 0, &icm42688_fifo_bufs[buf_idx][0],
122+
ICM42688_FIFO_BUF_LEN, (void *)(uintptr_t)buf_idx);
123+
rtio_spsc_produce(r->sq);
124+
125+
rtio_submit(r, 0);
126+
127+
}
128+
129+
LOG_INF("Checking In, Sensor Overflows %u", overflows);
130+
131+
/* All done streaming */
132+
sensor_fifo_stop(icm42688);
133+
134+
LOG_INF("DONE! FIFO should be DISABLED");
135+
}
136+
137+
void main(void)
138+
{
139+
const struct device *icm42688 = DEVICE_DT_GET_ONE(invensense_icm42688);
140+
struct sensor_value accel[3];
141+
struct sensor_value gyro[3];
142+
struct sensor_value temp;
143+
144+
145+
LOG_INF("TDK RoboKit1 Sample");
146+
147+
148+
if (!device_is_ready(icm42688)) {
149+
LOG_INF("%s: device not ready.", icm42688->name);
150+
return;
151+
}
152+
153+
LOG_INF("Fetch + Read");
154+
155+
/* A few polling readings */
156+
for (int i = 0; i < 10; i++) {
157+
158+
/* Fetch everything */
159+
sensor_sample_fetch_chan(icm42688, SENSOR_CHAN_ALL);
160+
161+
sensor_channel_get(icm42688, SENSOR_CHAN_ACCEL_XYZ, accel);
162+
sensor_channel_get(icm42688, SENSOR_CHAN_GYRO_XYZ, gyro);
163+
sensor_channel_get(icm42688, SENSOR_CHAN_DIE_TEMP, &temp);
164+
165+
LOG_INF("ICM42688: Accel (m/s^2): x: %d.%06d, y: %d.%06d, z: %d.%06d",
166+
accel[0].val1, accel[0].val2,
167+
accel[1].val1, accel[1].val2,
168+
accel[2].val1, accel[2].val2);
169+
LOG_INF("ICM42688: Gyro (rad/s): x: %d.%06d, y: %d.%06d, z: %d.%06di",
170+
gyro[0].val1, gyro[0].val2,
171+
gyro[1].val1, gyro[1].val2,
172+
gyro[2].val1, gyro[2].val2);
173+
LOG_INF("ICM42688: Temp (C): %d.%06d\n",
174+
temp.val1, temp.val2);
175+
176+
k_sleep(K_MSEC(100));
177+
}
178+
179+
LOG_INF("Showing under/over flows with 1 buffer queue");
180+
fifo_stream(icm42688, &r1, 1);
181+
182+
LOG_INF("Showing no under/over flows with 4 buffer queue");
183+
fifo_stream(icm42688, &r4, 4);
184+
185+
LOG_INF("Done!");
186+
187+
while (true) {
188+
k_msleep(1000);
189+
}
190+
}

0 commit comments

Comments
 (0)