1 /*
2 * Copyright 2022 NXP
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/kernel.h>
8 #include <zephyr/sd/sdmmc.h>
9 #include <zephyr/device.h>
10 #include <zephyr/drivers/disk.h>
11 #include <zephyr/ztest.h>
12
13
14 #define SECTOR_COUNT 32
15 #define SECTOR_SIZE 512 /* subsystem should set all cards to 512 byte blocks */
16 #define BUF_SIZE SECTOR_SIZE * SECTOR_COUNT
17 static const struct device *const sdhc_dev = DEVICE_DT_GET(DT_ALIAS(sdhc0));
18 static struct sd_card card;
19 static uint8_t buf[BUF_SIZE] __aligned(CONFIG_SDHC_BUFFER_ALIGNMENT);
20 static uint8_t check_buf[BUF_SIZE] __aligned(CONFIG_SDHC_BUFFER_ALIGNMENT);
21 static uint32_t sector_size;
22 static uint32_t sector_count;
23
24 #define SDMMC_UNALIGN_OFFSET 1
25
26
27 /*
28 * Verify that SD stack can initialize an SD card
29 * This test must run first, to ensure the card is initialized.
30 */
ZTEST(sd_stack,test_0_init)31 ZTEST(sd_stack, test_0_init)
32 {
33 int ret;
34
35 zassert_true(device_is_ready(sdhc_dev), "SDHC device is not ready");
36
37 ret = sd_is_card_present(sdhc_dev);
38 zassert_equal(ret, 1, "SD card not present in slot");
39
40 ret = sd_init(sdhc_dev, &card);
41 zassert_equal(ret, 0, "Card initialization failed");
42 }
43
44 /* Verify that SD stack returns valid IOCTL values */
ZTEST(sd_stack,test_ioctl)45 ZTEST(sd_stack, test_ioctl)
46 {
47 int ret;
48
49 ret = sdmmc_ioctl(&card, DISK_IOCTL_GET_SECTOR_COUNT, §or_count);
50 zassert_equal(ret, 0, "IOCTL sector count read failed");
51 TC_PRINT("SD card reports sector count of %d\n", sector_count);
52
53 ret = sdmmc_ioctl(&card, DISK_IOCTL_GET_SECTOR_SIZE, §or_size);
54 zassert_equal(ret, 0, "IOCTL sector size read failed");
55 TC_PRINT("SD card reports sector size of %d\n", sector_size);
56 }
57
58
59 /* Verify that SD stack can read from an SD card */
ZTEST(sd_stack,test_read)60 ZTEST(sd_stack, test_read)
61 {
62 int ret;
63 int block_addr = 0;
64
65 /* Try simple reads from start of SD card */
66
67 ret = sdmmc_read_blocks(&card, buf, block_addr, 1);
68 zassert_equal(ret, 0, "Single block card read failed");
69
70 ret = sdmmc_read_blocks(&card, buf, block_addr, SECTOR_COUNT / 2);
71 zassert_equal(ret, 0, "Multiple block card read failed");
72
73 /* Try a series of reads from the same block */
74 block_addr = sector_count / 2;
75 for (int i = 0; i < 10; i++) {
76 ret = sdmmc_read_blocks(&card, buf, block_addr, SECTOR_COUNT);
77 zassert_equal(ret, 0, "Multiple reads from same addr failed");
78 }
79 /* Verify that out of bounds read fails */
80 block_addr = sector_count;
81 ret = sdmmc_read_blocks(&card, buf, block_addr, 1);
82 zassert_not_equal(ret, 0, "Out of bounds read should fail");
83
84 block_addr = sector_count - 2;
85 ret = sdmmc_read_blocks(&card, buf, block_addr, 2);
86 zassert_equal(ret, 0, "Read from end of card failed");
87
88 /* Verify that unaligned reads work */
89 block_addr = 3;
90 ret = sdmmc_read_blocks(&card, buf + SDMMC_UNALIGN_OFFSET,
91 block_addr, SECTOR_COUNT - 1);
92 zassert_equal(ret, 0, "Unaligned read failed");
93 }
94
95 /* Verify that SD stack can write to an SD card */
ZTEST(sd_stack,test_write)96 ZTEST(sd_stack, test_write)
97 {
98 int ret;
99 int block_addr = 0;
100
101 /* Try simple writes from start of SD card */
102
103 ret = sdmmc_write_blocks(&card, buf, block_addr, 1);
104 zassert_equal(ret, 0, "Single block card write failed");
105
106 ret = sdmmc_write_blocks(&card, buf, block_addr, SECTOR_COUNT / 2);
107 zassert_equal(ret, 0, "Multiple block card write failed");
108
109 /* Try a series of reads from the same block */
110 block_addr = sector_count / 2;
111 for (int i = 0; i < 10; i++) {
112 ret = sdmmc_write_blocks(&card, buf, block_addr, SECTOR_COUNT);
113 zassert_equal(ret, 0, "Multiple writes to same addr failed");
114 }
115 /* Verify that out of bounds write fails */
116 block_addr = sector_count;
117 ret = sdmmc_write_blocks(&card, buf, block_addr, 1);
118 zassert_not_equal(ret, 0, "Out of bounds write should fail");
119
120 block_addr = sector_count - 2;
121 ret = sdmmc_write_blocks(&card, buf, block_addr, 2);
122 zassert_equal(ret, 0, "Write to end of card failed");
123
124 /* Verify that unaligned writes work */
125 block_addr = 3;
126 ret = sdmmc_write_blocks(&card, buf + SDMMC_UNALIGN_OFFSET,
127 block_addr, SECTOR_COUNT - 1);
128 zassert_equal(ret, 0, "Unaligned write failed");
129 }
130
131 /* Test reads and writes interleaved, to verify data is making it on disk */
ZTEST(sd_stack,test_rw)132 ZTEST(sd_stack, test_rw)
133 {
134 int ret;
135 int block_addr = 0;
136
137 /* Zero the write buffer */
138 memset(buf, 0, BUF_SIZE);
139 memset(check_buf, 0, BUF_SIZE);
140 ret = sdmmc_write_blocks(&card, buf, block_addr, SECTOR_COUNT / 2);
141 zassert_equal(ret, 0, "Write to card failed");
142 /* Verify that a read from this area is empty */
143 ret = sdmmc_read_blocks(&card, buf, block_addr, SECTOR_COUNT / 2);
144 zassert_equal(ret, 0, "Read from card failed");
145 zassert_mem_equal(buf, check_buf, BUF_SIZE,
146 "Read of erased area was not zero");
147
148 /* Now write nonzero data block */
149 for (int i = 0; i < sizeof(buf); i++) {
150 check_buf[i] = buf[i] = (uint8_t)i;
151 }
152
153 ret = sdmmc_write_blocks(&card, buf, block_addr, SECTOR_COUNT);
154 zassert_equal(ret, 0, "Write to card failed");
155 /* Clear the read buffer, then write to it again */
156 memset(buf, 0, BUF_SIZE);
157 ret = sdmmc_read_blocks(&card, buf, block_addr, SECTOR_COUNT);
158 zassert_equal(ret, 0, "Read from card failed");
159 zassert_mem_equal(buf, check_buf, BUF_SIZE,
160 "Read of written area was not correct");
161
162 block_addr = (sector_count / 3);
163 for (int i = 0; i < 10; i++) {
164 /* Verify that unaligned writes work */
165 ret = sdmmc_write_blocks(&card, buf + SDMMC_UNALIGN_OFFSET,
166 block_addr, SECTOR_COUNT - 1);
167 zassert_equal(ret, 0, "Write to card failed");
168 /* Zero check buffer and read into it */
169 memset(check_buf + SDMMC_UNALIGN_OFFSET, 0,
170 (SECTOR_COUNT - 1) * sector_size);
171 ret = sdmmc_read_blocks(&card, check_buf + SDMMC_UNALIGN_OFFSET,
172 block_addr, (SECTOR_COUNT - 1));
173 zassert_equal(ret, 0, "Read from card failed");
174 zassert_mem_equal(buf + SDMMC_UNALIGN_OFFSET,
175 check_buf + SDMMC_UNALIGN_OFFSET,
176 (SECTOR_COUNT - 1) * sector_size,
177 "Unaligned read of written area was not correct");
178 }
179 }
180
181 /* Simply dump the card configuration. */
ZTEST(sd_stack,test_card_config)182 ZTEST(sd_stack, test_card_config)
183 {
184 switch (card.card_voltage) {
185 case SD_VOL_1_2_V:
186 TC_PRINT("Card voltage: 1.2V\n");
187 break;
188 case SD_VOL_1_8_V:
189 TC_PRINT("Card voltage: 1.8V\n");
190 break;
191 case SD_VOL_3_0_V:
192 TC_PRINT("Card voltage: 3.0V\n");
193 break;
194 case SD_VOL_3_3_V:
195 TC_PRINT("Card voltage: 3.3V\n");
196 break;
197 default:
198 zassert_unreachable("Card voltage is not known value");
199 }
200 zassert_equal(card.status, CARD_INITIALIZED, "Card status is not OK");
201 switch (card.card_speed) {
202 case SD_TIMING_SDR12:
203 TC_PRINT("Card timing: SDR12\n");
204 break;
205 case SD_TIMING_SDR25:
206 TC_PRINT("Card timing: SDR25\n");
207 break;
208 case SD_TIMING_SDR50:
209 TC_PRINT("Card timing: SDR50\n");
210 break;
211 case SD_TIMING_SDR104:
212 TC_PRINT("Card timing: SDR104\n");
213 break;
214 case SD_TIMING_DDR50:
215 TC_PRINT("Card timing: DDR50\n");
216 break;
217 default:
218 zassert_unreachable("Card timing is not known value");
219 }
220 switch (card.type) {
221 case CARD_SDIO:
222 TC_PRINT("Card type: SDIO\n");
223 break;
224 case CARD_SDMMC:
225 TC_PRINT("Card type: SDMMC\n");
226 break;
227 case CARD_COMBO:
228 TC_PRINT("Card type: combo card\n");
229 break;
230 default:
231 zassert_unreachable("Card type is not known value");
232 }
233 if (card.sd_version >= SD_SPEC_VER3_0) {
234 TC_PRINT("Card spec: 3.0\n");
235 } else if (card.sd_version >= SD_SPEC_VER2_0) {
236 TC_PRINT("Card spec: 2.0\n");
237 } else if (card.sd_version >= SD_SPEC_VER1_1) {
238 TC_PRINT("Card spec: 1.1\n");
239 } else if (card.sd_version >= SD_SPEC_VER1_0) {
240 TC_PRINT("Card spec: 1.0\n");
241 } else {
242 zassert_unreachable("Card spec is unknown value");
243 }
244 }
245
246 ZTEST_SUITE(sd_stack, NULL, NULL, NULL, NULL, NULL);
247