1 /*
2 * Copyright (C) 2017 ALLWINNERTECH TECHNOLOGY CO., LTD. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the
12 * distribution.
13 * 3. Neither the name of ALLWINNERTECH TECHNOLOGY CO., LTD. nor the names of
14 * its contributors may be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30 #include <string.h>
31 #include <stdio.h>
32
33
34 #include "sys/sys_debug.h"
35
36 #include "os_time.h"
37 //#include "FreeRTOS.h"
38 #include "os_semaphore.h"
39
40 #include "hal_def.h"
41 #include "hal_ccm.h"
42 #include "hal_sdhost.h"
43 #include "sdmmc.h"
44 #include "sdio.h"
45
46 #include "_sd_define.h"
47 #include "_sdhost.h"
48
49
50 #define TEST_SD
51 #define TEST_SD_WRITE
52
53 #ifdef TEST_SD
54
55 #define SIZE_1K (1024)
56 #define SIZE_1M (SIZE_1K*SIZE_1K)
57
58 #define READ_WRITE_SINGLE_SIZE (16*SIZE_1K)
59 #define READ_WRITE_TOTAL_SIZE (8*SIZE_1M)
60
61 struct sdmmc_tester {
62 struct mmc_card *card;
63 SDCard_InitTypeDef card_param;
64 SDC_InitTypeDef sdc_param;
65 uint16_t sdc_id;
66 uint16_t card_id;
67 uint8_t wbuf[READ_WRITE_SINGLE_SIZE];
68 uint8_t rbuf[READ_WRITE_SINGLE_SIZE];
69 #ifdef CONFIG_DETECT_CARD
70 OS_Semaphore_t card_present_sem;
71 #endif
72 };
73
74 static struct sdmmc_tester *sdmmc_test = NULL;
75
76 #ifdef CONFIG_DETECT_CARD
77 static int detect_status = -1;
card_detect(uint32_t present)78 void card_detect(uint32_t present)
79 {
80 if (present) {
81 detect_status = 0;
82 rt_kprintf("%s insert\n", __func__);
83 if (mmc_card_create(sdmmc_test->card_id, &sdmmc_test->card_param) != 0) {
84 rt_kprintf("mmc create fail\n");
85 return ;
86 }
87 sdmmc_test->card = mmc_card_open(sdmmc_test->card_id);
88 if (sdmmc_test->card == NULL) {
89 rt_kprintf("mmc open fail\n");
90 return ;
91 }
92 /* scan card for detect card is exist? */
93 if (!mmc_card_present(sdmmc_test->card)) {
94 // if (mmc_rescan(sdmmc_test->card, sdmmc_test->card->id)) {
95 sdmmc_test->card->type = MMC_TYPE_SD;
96 if (mmc_rescan(sdmmc_test->card, sdmmc_test->sdc_id)) {
97 rt_kprintf("Initial card failed!!\n");
98 mmc_card_close(sdmmc_test->card_id);
99 detect_status = -1;
100 return ;
101 } else {
102 rt_kprintf("Initial card success. capacity :%dMB\n", sdmmc_test->card->csd.capacity / 1024);
103 mmc_card_close(sdmmc_test->card_id);
104 #ifndef CONFIG_KERNEL_FREERTOS
105 // void mount_sdmmc_filesystem(int card_id);
106 // mount_sdmmc_filesystem((int)sdmmc_test->card_id);
107 #endif
108 SDC_SemPost(&sdmmc_test->card_present_sem);
109 }
110 } else {
111 rt_kprintf("%s not eixst\n", __func__);
112 mmc_card_close(sdmmc_test->card_id);
113 return ;
114 }
115 } else {
116 struct mmc_card *card;
117
118 rt_kprintf("%s removed\n", __func__);
119 card = mmc_card_open(sdmmc_test->card_id);
120 if (card == NULL) {
121 rt_kprintf("card open fail\n");
122 } else {
123 if (mmc_card_present(card)) {
124 mmc_card_deinit(card);
125 }
126 mmc_card_close(sdmmc_test->card_id);
127 #ifndef CONFIG_KERNEL_FREERTOS
128 // void unmount_sdmmc_filesystem(void);
129 // unmount_sdmmc_filesystem();
130 #endif
131 mmc_card_delete(sdmmc_test->card_id);
132 }
133 }
134 }
135 #endif
136 //#define WIFI_DEBUG 0
137 // #define DETECT_BY_GPIO 1
mmc_test_init(uint32_t host_id,SDC_InitTypeDef * sdc_param,uint32_t scan)138 int32_t mmc_test_init(uint32_t host_id, SDC_InitTypeDef *sdc_param, uint32_t scan)
139 {
140 struct mmc_host *host;
141
142 if (!sdmmc_test) {
143 sdmmc_test = malloc(sizeof(struct sdmmc_tester));
144 if (!sdmmc_test) {
145 rt_kprintf("malloc faild!\n");
146 return -1;
147 }
148 memset(sdmmc_test, 0, sizeof(struct sdmmc_tester));
149 }
150
151 if (sdc_param)
152 memcpy(&sdmmc_test->sdc_param, sdc_param, sizeof(SDC_InitTypeDef));
153
154 #ifdef CONFIG_DETECT_CARD
155 OS_SemaphoreCreate(&sdmmc_test->card_present_sem, 0, OS_SEMAPHORE_MAX_COUNT);
156
157 if (!sdc_param) {
158 #ifndef DETECT_BY_GPIO
159 sdmmc_test->sdc_param.cd_mode = CARD_ALWAYS_PRESENT;
160 #else
161 sdmmc_test->sdc_param.cd_mode = CARD_DETECT_BY_GPIO_IRQ;
162 #endif
163 sdmmc_test->sdc_param.cd_cb = &card_detect;
164 #ifndef WIFI_DEBUG
165 sdmmc_test->sdc_param.debug_mask = (ROM_INF_MASK | \
166 ROM_WRN_MASK | ROM_ERR_MASK | ROM_ANY_MASK);
167 #else
168 sdmmc_test->sdc_param.debug_mask = (ROM_DUMP_MASK | ROM_DBG_MASK | ROM_INF_MASK | \
169 ROM_WRN_MASK | ROM_ERR_MASK | ROM_ANY_MASK);
170 #endif
171 sdmmc_test->sdc_param.dma_use = 1;
172 }
173 #endif
174 if (!sdc_param)
175 sdc_param = &sdmmc_test->sdc_param;
176 #ifdef WIFI_DEBUG
177 sdmmc_test->card_param.debug_mask = (ROM_DUMP_MASK | ROM_DBG_MASK | ROM_INF_MASK | \
178 ROM_WRN_MASK | ROM_ERR_MASK | ROM_ANY_MASK);
179 #else
180 sdmmc_test->card_param.debug_mask = (ROM_INF_MASK | \
181 ROM_WRN_MASK | ROM_ERR_MASK | ROM_ANY_MASK);
182 #endif
183 host = hal_sdc_create(host_id, sdc_param);
184 host->State = SDC_STATE_RESET;
185 hal_sdc_init(host);
186 //HAL_SDC_SetHighSpeed(host);
187 sdmmc_test->sdc_id = host_id;
188 sdmmc_test->card_id = host_id;
189
190 if (scan && sdmmc_test->sdc_param.cd_mode == CARD_ALWAYS_PRESENT) {
191 card_detect(1);
192 return detect_status;
193 }
194
195 return 0;
196 }
197
mmc_test_exit(uint16_t sd_id,uint16_t host_id)198 int32_t mmc_test_exit(uint16_t sd_id, uint16_t host_id)
199 {
200 struct mmc_card *card;
201 struct mmc_host *host;
202
203 if (!sdmmc_test->card || !sdmmc_test->card->host ||
204 sdmmc_test->card->id != sd_id || sdmmc_test->sdc_id != host_id) {
205 if (!sdmmc_test->card || !sdmmc_test->card->host)
206 rt_kprintf("no card found\n");
207 else
208 rt_kprintf("wrong card id:%d<->%d host id:%ld<->%d\n", sd_id, host_id,
209 HAL_PR_SZ_L(sdmmc_test->card->id), sdmmc_test->sdc_id);
210 return 0;
211 }
212
213 card = mmc_card_open(sdmmc_test->card_id);
214 if (card == NULL) {
215 rt_kprintf("card open fail\n");
216 } else {
217 if (mmc_card_present(card)) {
218 mmc_card_deinit(card);
219 }
220 mmc_card_close(sdmmc_test->card_id);
221 mmc_card_delete(sdmmc_test->card_id);
222 }
223
224 #if 0
225 host = HAL_SDC_Open(host_id);
226 HAL_SDC_Close(host_id);
227 #endif
228 hal_sdc_deinit(sd_id);
229 #if 0
230 HAL_SDC_Destory(host);
231 #endif
232
233 #ifdef CONFIG_DETECT_CARD
234 OS_SemaphoreDelete(&sdmmc_test->card_present_sem);
235 #endif
236
237 if (sdmmc_test) {
238 free(sdmmc_test);
239 sdmmc_test = NULL;
240 }
241
242
243 return 0;
244 }
245
mmc_scan_init(uint16_t sd_id,uint16_t sdc_id,SDCard_InitTypeDef * card_param)246 struct mmc_card *mmc_scan_init(uint16_t sd_id, uint16_t sdc_id, SDCard_InitTypeDef *card_param)
247 {
248 struct mmc_card *card;
249
250 if (!card_param) {
251 card_param = &sdmmc_test->card_param;
252 sdmmc_test->card_param.debug_mask = ROM_WRN_MASK | ROM_ERR_MASK | ROM_ANY_MASK;
253 }
254 if (mmc_card_create(sd_id, card_param) != 0) {
255 rt_kprintf("mmc create fail\n");
256 return NULL;
257 }
258 card = mmc_card_open(sd_id);
259 if (card == NULL) {
260 rt_kprintf("mmc open fail\n");
261 return NULL;
262 }
263 if (!mmc_card_present(card)) {
264 int mmc_ret = mmc_rescan(card, sdc_id);
265 if (mmc_ret != 0) {
266 rt_kprintf("mmc scan fail\n");
267 mmc_card_close(sd_id);
268 return NULL;
269 } else {
270 rt_kprintf("mmc init\n");
271 }
272 }
273 mmc_card_close(sd_id);
274 sdmmc_test->card = card;
275
276 return card;
277 }
278
mmc_test(uint32_t host_id,uint32_t cd_mode,uint32_t sdc_degmask,uint32_t card_dbgmask)279 int32_t mmc_test(uint32_t host_id, uint32_t cd_mode, uint32_t sdc_degmask, uint32_t card_dbgmask)
280 {
281 int32_t err;
282 uint32_t i, cnt = 0;
283 SDC_InitTypeDef sdc_param = { 0 };
284
285 sdc_param.cd_mode = cd_mode;
286 sdc_param.cd_cb = &card_detect;
287 sdc_param.debug_mask = sdc_degmask;
288 sdc_param.dma_use = 1;
289
290 //if (mmc_test_init(host_id, &sdc_param, 1)) {
291 if (mmc_test_init(host_id, &sdc_param, 1)) {
292 return -1;
293 }
294
295 memset((void *)sdmmc_test->wbuf, 0x55, 128);
296 memset((void *)&sdmmc_test->wbuf[128], 0xaa, 128);
297
298 for (i = 0; i < 256; i ++)
299 sdmmc_test->wbuf[256 + i] = i;
300
301 memcpy((void *)&sdmmc_test->wbuf[512], (void *)sdmmc_test->wbuf, 512);
302
303 sdmmc_test->card_param.debug_mask = card_dbgmask;
304
305
306 // if (mmc_test_init(host_id, &sdc_param, 1)) {
307 // return -1;
308 // }
309
310
311 sdmmc_test->card_param.type = MMC_TYPE_SD;
312
313 while (cnt++ < 1) {
314 uint32_t throuth_mb, throuth_kb;
315 OS_Time_t tick_use;
316
317 rt_kprintf("%s,%d count:%lu\n", __func__, __LINE__, HAL_PR_SZ_L(cnt));
318
319 #ifdef CONFIG_DETECT_CARD
320 if (!mmc_card_present(sdmmc_test->card) || (cd_mode != CARD_ALWAYS_PRESENT))
321 OS_SemaphoreWait(&sdmmc_test->card_present_sem, OS_WAIT_FOREVER);
322 #endif
323
324 struct mmc_card *card = mmc_card_open(sdmmc_test->card_id);
325 card->debug_mask = card_dbgmask;
326 if (card == NULL) {
327 rt_kprintf("mmc open fail\n");
328 goto err_out;
329 }
330
331 #ifdef TEST_SD_WRITE
332 tick_use = OS_GetTicks();
333 err = mmc_block_write(sdmmc_test->card, sdmmc_test->wbuf, 0, 1);
334 tick_use = OS_GetTicks() - tick_use;
335 if (err) {
336 goto err_out;
337 } else {
338 rt_kprintf("%s 1 block write ok, 512B use:%lu ms\n", __func__,
339 HAL_PR_SZ_L((uint32_t)OS_TicksToMSecs(tick_use)));
340 }
341 #endif
342 memset((void *)sdmmc_test->rbuf, 0, 512);
343 tick_use = OS_GetTicks();
344 err = mmc_block_read(sdmmc_test->card, sdmmc_test->rbuf, 0, 1);
345 tick_use = OS_GetTicks() - tick_use;
346 if (err) {
347 goto err_out;
348 } else {
349 rt_kprintf("%s 1 block read ok, 512B use:%lu ms\n", __func__,
350 HAL_PR_SZ_L((uint32_t)OS_TicksToMSecs(tick_use)));
351 #ifndef TEST_SD_WRITE
352 print_hex_dump_words(sdmmc_test->rbuf, 512);
353 #endif
354 }
355 #ifdef TEST_SD_WRITE
356 if (memcmp((void *)sdmmc_test->wbuf, (void *)sdmmc_test->rbuf, 512)) {
357 goto err_out;
358 } else
359 rt_kprintf("%s,%d mmc 1 block rw ok\n", __func__, __LINE__);
360
361 tick_use = OS_GetTicks();
362 for (i = 0; i < READ_WRITE_TOTAL_SIZE/READ_WRITE_SINGLE_SIZE; i++) {
363 err = mmc_block_write(sdmmc_test->card, sdmmc_test->wbuf, 3 + i * (READ_WRITE_SINGLE_SIZE/512),
364 READ_WRITE_SINGLE_SIZE/512);
365 if (err)
366 break;
367 if (i % 50 == 0)
368 rt_kprintf("%s, wirite cnt:%lu\n", __func__, HAL_PR_SZ_L(i));
369 }
370 tick_use = OS_GetTicks() - tick_use;
371 if (err) {
372 rt_kprintf("%s,%d mmc mult blocks write err!\n", __func__, __LINE__);
373 goto err_out;
374 } else {
375 throuth_kb = READ_WRITE_TOTAL_SIZE/SIZE_1K*1000/(uint32_t)OS_TicksToMSecs(tick_use);
376 throuth_mb = throuth_kb/1000;
377 rt_kprintf("%s mult blocks write ok, %d MB use:%lu ms, throughput:%lu.%lu MB/S\n",
378 __func__, READ_WRITE_TOTAL_SIZE/SIZE_1M, HAL_PR_SZ_L((uint32_t)OS_TicksToMSecs(tick_use)),
379 HAL_PR_SZ_L(throuth_mb), HAL_PR_SZ_L(throuth_kb - throuth_mb));
380 }
381 #endif
382
383 tick_use = OS_GetTicks();
384 for (i = 0; i < READ_WRITE_TOTAL_SIZE/READ_WRITE_SINGLE_SIZE; i++) {
385 err = mmc_block_read(sdmmc_test->card, sdmmc_test->rbuf, 3 + i * (READ_WRITE_SINGLE_SIZE/512),
386 READ_WRITE_SINGLE_SIZE/512);
387 if (err)
388 break;
389 }
390 tick_use = OS_GetTicks() - tick_use;
391 if (err) {
392 rt_kprintf("%s,%d mmc mult blocks read err!\n", __func__, __LINE__);
393 goto err_out;
394 } else {
395 throuth_kb = READ_WRITE_TOTAL_SIZE/SIZE_1K*1000/(uint32_t)OS_TicksToMSecs(tick_use);
396 throuth_mb = throuth_kb/1000;
397 rt_kprintf("%s mult blocks read ok, %d MB use:%lu ms, throughput:%lu.%lu MB/S\n",
398 __func__, READ_WRITE_TOTAL_SIZE/SIZE_1M, HAL_PR_SZ_L((uint32_t)OS_TicksToMSecs(tick_use)),
399 HAL_PR_SZ_L(throuth_mb), HAL_PR_SZ_L(throuth_kb - throuth_mb));
400 }
401
402 memset((void *)sdmmc_test->rbuf, 0, READ_WRITE_SINGLE_SIZE);
403 err = mmc_block_read(sdmmc_test->card, sdmmc_test->rbuf, 3, READ_WRITE_SINGLE_SIZE/512);
404 if (err) {
405 goto err_out;
406 } else
407 rt_kprintf("%s %d blocks read ok\n", __func__, READ_WRITE_SINGLE_SIZE/512);
408
409 #ifdef TEST_SD_WRITE
410 if (memcmp((void *)sdmmc_test->wbuf, (void *)sdmmc_test->rbuf, 1024)) { /* check 1024B */
411 rt_kprintf("%s %d mmc blocks rw failed\n", __func__, READ_WRITE_SINGLE_SIZE/512);
412 goto err_out;
413 } else
414 rt_kprintf("%s %d mmc blocks rw ok\n", __func__, READ_WRITE_SINGLE_SIZE/512);
415 #endif
416 mmc_card_close(sdmmc_test->card_id);
417
418 OS_MSleep(1000);
419 }
420
421 mmc_test_exit(host_id, sdmmc_test->card_id);
422
423 return 0;
424
425 err_out:
426 #ifdef TEST_SD_WRITE
427 rt_kprintf("%s,%d mmc block rw failed\n", __func__, __LINE__);
428 rt_kprintf("rbuf:\n");
429 print_hex_dump_words(sdmmc_test->rbuf, SIZE_1K);
430 rt_kprintf("wbuf:\n");
431 print_hex_dump_words(sdmmc_test->wbuf, 512);
432 #endif
433 #ifndef CONFIG_DETECT_CARD
434 out:
435 #endif
436 mmc_test_exit(host_id, sdmmc_test->card_id);
437 return -1;
438 }
439 #endif /* TEST_SD */
440