1 /*
2 * Copyright (c) 2024 STMicroelectronics
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/kernel.h>
8 #include <zephyr/device.h>
9 #include <zephyr/devicetree.h>
10 #include <zephyr/drivers/gpio.h>
11 #include <zephyr/sys/printk.h>
12 #include <zephyr/pm/pm.h>
13 #include <zephyr/pm/device_runtime.h>
14 #include <zephyr/drivers/adc.h>
15 #include <zephyr/drivers/entropy.h>
16 #include <zephyr/drivers/spi.h>
17 #include <string.h>
18 #include <stdio.h>
19 #include <assert.h>
20
21 #define SLEEP_TIME_STOP0_MS 800
22 #define SLEEP_TIME_STOP1_MS 1500
23 #define SLEEP_TIME_STANDBY_MS 3000
24 #define SLEEP_TIME_BUSY_MS 2000
25
26 static const struct gpio_dt_spec led =
27 GPIO_DT_SPEC_GET(DT_ALIAS(led2), gpios);
28
29 #if !DT_NODE_EXISTS(DT_PATH(zephyr_user)) || \
30 !DT_NODE_HAS_PROP(DT_PATH(zephyr_user), io_channels)
31 #error "No suitable devicetree overlay specified"
32 #endif
33
34 #define DT_SPEC_AND_COMMA(node_id, prop, idx) \
35 ADC_DT_SPEC_GET_BY_IDX(node_id, idx),
36
37 /* Data of ADC io-channels specified in devicetree. */
38 static const struct adc_dt_spec adc_channels[] = {
39 DT_FOREACH_PROP_ELEM(DT_PATH(zephyr_user), io_channels,
40 DT_SPEC_AND_COMMA)
41 };
42
43 const struct device *rng_dev;
44
45 #define BUFFER_LENGTH 3
46
47 static uint8_t entropy_buffer[BUFFER_LENGTH] = {0};
48
49 #define SPI_TEST_DEV DT_COMPAT_GET_ANY_STATUS_OKAY(test_spi_loopback)
50
51 #define FRAME_SIZE (8)
52
53 #define SPI_OP(frame_size) SPI_OP_MODE_MASTER | SPI_MODE_CPOL | \
54 SPI_MODE_CPHA | SPI_WORD_SET(frame_size) | SPI_LINES_SINGLE
55
56 static struct spi_dt_spec spi_test_dev = SPI_DT_SPEC_GET(SPI_TEST_DEV, SPI_OP(FRAME_SIZE), 0);
57
58 #define SPI_BUF_SIZE 18
59
60 static const char spi_tx_data[SPI_BUF_SIZE] = "0123456789abcdef-\0";
61 static __aligned(32) char spi_buffer_tx[SPI_BUF_SIZE] __used;
62 static __aligned(32) char spi_buffer_rx[SPI_BUF_SIZE] __used;
63
64 static uint8_t spi_buffer_print_tx[SPI_BUF_SIZE * 5 + 1];
65 static uint8_t spi_buffer_print_rx[SPI_BUF_SIZE * 5 + 1];
66
to_display_format(const uint8_t * src,size_t size,char * dst)67 static void to_display_format(const uint8_t *src, size_t size, char *dst)
68 {
69 size_t i;
70
71 for (i = 0; i < size; i++) {
72 sprintf(dst + 5 * i, "0x%02x,", src[i]);
73 }
74 }
75
spi_test(void)76 static int spi_test(void)
77 {
78 const struct spi_buf tx_bufs[] = {
79 {
80 .buf = spi_buffer_tx,
81 .len = SPI_BUF_SIZE,
82 },
83 };
84 const struct spi_buf rx_bufs[] = {
85 {
86 .buf = spi_buffer_rx,
87 .len = SPI_BUF_SIZE,
88 },
89 };
90 const struct spi_buf_set tx = {
91 .buffers = tx_bufs,
92 .count = ARRAY_SIZE(tx_bufs)
93 };
94 const struct spi_buf_set rx = {
95 .buffers = rx_bufs,
96 .count = ARRAY_SIZE(rx_bufs)
97 };
98
99 int ret;
100
101 ret = spi_transceive_dt(&spi_test_dev, &tx, &rx);
102 if (ret) {
103 printk("SPI transceive failed: %d\n", ret);
104 return ret;
105 }
106
107 if (memcmp(spi_buffer_tx, spi_buffer_rx, SPI_BUF_SIZE)) {
108 to_display_format(spi_buffer_tx, SPI_BUF_SIZE, spi_buffer_print_tx);
109 to_display_format(spi_buffer_rx, SPI_BUF_SIZE, spi_buffer_print_rx);
110 printk("Buffer contents are different\n");
111 printk("tx: %s\n", spi_buffer_print_tx);
112 printk("rx: %s\n", spi_buffer_print_rx);
113 return -1;
114 }
115
116 return 0;
117 }
118
spi_setup(void)119 static void spi_setup(void)
120 {
121 memset(spi_buffer_tx, 0, sizeof(spi_buffer_tx));
122 memcpy(spi_buffer_tx, spi_tx_data, sizeof(spi_tx_data));
123
124 if (!spi_is_ready_dt(&spi_test_dev)) {
125 printk("Fast spi lookback device is not ready\n");
126 }
127 }
128
adc_test(void)129 static int adc_test(void)
130 {
131 int err;
132 static uint32_t count;
133 uint16_t buf;
134 struct adc_sequence sequence = {
135 .buffer = &buf,
136 /* buffer size in bytes, not number of samples */
137 .buffer_size = sizeof(buf),
138 };
139
140 /* Configure channels individually prior to sampling. */
141 for (size_t i = 0U; i < ARRAY_SIZE(adc_channels); i++) {
142 if (!adc_is_ready_dt(&adc_channels[i])) {
143 printk("ADC controller device %s not ready\n", adc_channels[i].dev->name);
144 return 0;
145 }
146
147 err = adc_channel_setup_dt(&adc_channels[i]);
148 if (err < 0) {
149 printk("Could not setup channel #%d (%d)\n", i, err);
150 return 0;
151 }
152 }
153
154 printk("ADC reading[%u]:\n", count++);
155 for (size_t i = 0U; i < ARRAY_SIZE(adc_channels); i++) {
156 int32_t val_mv;
157
158 printk("- %s, channel %d: ",
159 adc_channels[i].dev->name,
160 adc_channels[i].channel_id);
161
162 (void)adc_sequence_init_dt(&adc_channels[i], &sequence);
163
164 err = adc_read_dt(&adc_channels[i], &sequence);
165 if (err < 0) {
166 printk("Could not read (%d)\n", err);
167 continue;
168 }
169
170 /*
171 * If using differential mode, the 16 bit value
172 * in the ADC sample buffer should be a signed 2's
173 * complement value.
174 */
175 if (adc_channels[i].channel_cfg.differential) {
176 val_mv = (int32_t)((int16_t)buf);
177 } else {
178 val_mv = (int32_t)buf;
179 }
180 printk("%"PRId32, val_mv);
181 err = adc_raw_to_millivolts_dt(&adc_channels[i],
182 &val_mv);
183 /* conversion to mV may not be supported, skip if not */
184 if (err < 0) {
185 printk(" (value in mV not available)\n");
186 } else {
187 printk(" = %"PRId32" mV\n", val_mv);
188 }
189 }
190
191 return 0;
192 }
193
print_buf(uint8_t * buffer)194 void print_buf(uint8_t *buffer)
195 {
196 int i;
197 int count = 0;
198
199 for (i = 0; i < BUFFER_LENGTH; i++) {
200 printk(" 0x%02x", buffer[i]);
201 if (buffer[i] == 0x00) {
202 count++;
203 }
204 }
205 printk("\n");
206 }
207
loop(void)208 static void loop(void)
209 {
210 gpio_pin_set_dt(&led, 1);
211 adc_test();
212 if (!IS_ENABLED(CONFIG_PM_S2RAM)) {
213 spi_test();
214 }
215 k_busy_wait(SLEEP_TIME_BUSY_MS*1000);
216 gpio_pin_set_dt(&led, 0);
217 }
218
main(void)219 int main(void)
220 {
221 __ASSERT_NO_MSG(gpio_is_ready_dt(&led));
222
223 rng_dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_entropy));
224 if (!device_is_ready(rng_dev)) {
225 printk("error: random device not ready");
226 }
227
228 spi_setup();
229
230 printk("Device ready\n");
231
232 while (true) {
233 gpio_pin_configure_dt(&led, GPIO_OUTPUT_ACTIVE);
234 loop();
235 k_msleep(SLEEP_TIME_STOP0_MS);
236 printk("Exit Stop0\n");
237
238 loop();
239 k_msleep(SLEEP_TIME_STOP1_MS);
240 printk("Exit Stop1\n");
241
242 (void)memset(entropy_buffer, 0x00, BUFFER_LENGTH);
243 entropy_get_entropy(rng_dev, (char *)entropy_buffer, BUFFER_LENGTH);
244 printk("Sync entropy: ");
245 print_buf(entropy_buffer);
246
247 loop();
248 gpio_pin_configure_dt(&led, GPIO_DISCONNECTED);
249 k_msleep(SLEEP_TIME_STANDBY_MS);
250 printk("Exit Standby\n");
251 }
252 return 0;
253 }
254