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