1 /*
2  * Copyright (c) 2022 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <stddef.h>
8 
9 #include <zephyr/kernel.h>
10 
11 #include <zephyr/sys/printk.h>
12 #include <zephyr/sys/util.h>
13 
14 #include "bs_types.h"
15 #include "bs_tracing.h"
16 #include "time_machine.h"
17 #include "bstests.h"
18 
19 /* There are 13 iterations of PHY update every 3 seconds, and based on actual
20  * simulation 10000 iterations are sufficient to finish these iterations with
21  * a stable 2M throughput value to be verified. If Central and Peripheral take
22  * different duration to complete these iterations, the test will fail due to
23  * the throughput calculated over one second duration will be low due to the
24  * connection being disconnected before the other device could complete all the
25  * iterations.
26  */
27 #define COUNT 10000
28 
29 /* Write Throughput calculation:
30  *  Measure interval = 1 s
31  *  Connection interval = 50 ms
32  *  No. of connection intervals = 20
33  *  Single Tx time, 2M PHY = 1064 us
34  *  tIFS = 150 us
35  *  Single Tx duration = 1214 us
36  *  Full duplex Tx-Rx duration = 2428 us
37  *  Implementation dependent event overhead = 340 us
38  *  Max. incomplete PDU time = 1064 us
39  *  Max. radio idle time per 1 second = (1064 + 340) * 20 = 28080 us
40  *  Packets per 1 second = (1000000 - 28080) / 2428 = 400.297
41  *  GATT Write data length = 244 bytes
42  *  Throughput = 400 * 244 * 8 = 780800 bps
43  */
44 #define WRITE_RATE 780800 /* GATT Write bps recorded in this test */
45 
46 extern uint32_t central_gatt_write(uint32_t count);
47 extern uint32_t peripheral_gatt_write(uint32_t count);
48 
49 #define FAIL(...)					\
50 	do {						\
51 		bst_result = Failed;			\
52 		bs_trace_error_time_line(__VA_ARGS__);	\
53 	} while (0)
54 
55 #define PASS(...)					\
56 	do {						\
57 		bst_result = Passed;			\
58 		bs_trace_info_time(1, __VA_ARGS__);	\
59 	} while (0)
60 
61 extern enum bst_result_t bst_result;
62 
test_central_main(void)63 static void test_central_main(void)
64 {
65 	uint32_t write_rate;
66 
67 	write_rate = central_gatt_write(COUNT);
68 
69 	printk("%s: Write Rate = %u bps\n", __func__, write_rate);
70 	if (write_rate == WRITE_RATE) {
71 		PASS("Central tests passed\n");
72 	} else {
73 		FAIL("Central tests failed\n");
74 	}
75 
76 	/* Give extra time for peripheral side to finish its iterations */
77 	k_sleep(K_SECONDS(1));
78 
79 	bs_trace_silent_exit(0);
80 }
81 
test_peripheral_main(void)82 static void test_peripheral_main(void)
83 {
84 	uint32_t write_rate;
85 
86 	write_rate = peripheral_gatt_write(COUNT);
87 
88 	printk("%s: Write Rate = %u bps\n", __func__, write_rate);
89 	if (write_rate == WRITE_RATE) {
90 		PASS("Peripheral tests passed\n");
91 	} else {
92 		FAIL("Peripheral tests failed\n");
93 	}
94 }
95 
test_gatt_write_init(void)96 static void test_gatt_write_init(void)
97 {
98 	bst_ticker_set_next_tick_absolute(60e6);
99 	bst_result = In_progress;
100 }
101 
test_gatt_write_tick(bs_time_t HW_device_time)102 static void test_gatt_write_tick(bs_time_t HW_device_time)
103 {
104 	bst_result = Failed;
105 	bs_trace_error_line("Test GATT Write finished.\n");
106 }
107 
108 static const struct bst_test_instance test_def[] = {
109 	{
110 		.test_id = "central",
111 		.test_descr = "Central GATT Write",
112 		.test_pre_init_f = test_gatt_write_init,
113 		.test_tick_f = test_gatt_write_tick,
114 		.test_main_f = test_central_main
115 	},
116 	{
117 		.test_id = "peripheral",
118 		.test_descr = "Peripheral GATT Write",
119 		.test_pre_init_f = test_gatt_write_init,
120 		.test_tick_f = test_gatt_write_tick,
121 		.test_main_f = test_peripheral_main
122 	},
123 	BSTEST_END_MARKER
124 };
125 
test_gatt_write_install(struct bst_test_list * tests)126 struct bst_test_list *test_gatt_write_install(struct bst_test_list *tests)
127 {
128 	return bst_add_tests(tests, test_def);
129 }
130 
131 bst_test_install_t test_installers[] = {
132 	test_gatt_write_install,
133 	NULL
134 };
135 
main(void)136 int main(void)
137 {
138 	bst_main();
139 	return 0;
140 }
141