device_test.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516
  1. /*
  2. * Copyright (c) 2006-2021, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2011-01-01 aozima the first version.
  9. * 2012-02-11 aozima add multiple sector speed test.
  10. * 2012-05-27 aozima use rt_deice API.
  11. */
  12. #include <rtthread.h>
  13. /* calculate speed */
  14. static void calculate_speed_print(rt_uint32_t speed)
  15. {
  16. rt_uint32_t k,m;
  17. k = speed/1024UL;
  18. if( k )
  19. {
  20. m = k/1024UL;
  21. if( m )
  22. {
  23. rt_kprintf("%d.%dMbyte/s",m,k%1024UL*100/1024UL);
  24. }
  25. else
  26. {
  27. rt_kprintf("%d.%dKbyte/s",k,speed%1024UL*100/1024UL);
  28. }
  29. }
  30. else
  31. {
  32. rt_kprintf("%dbyte/s",speed);
  33. }
  34. }
  35. static rt_err_t _block_device_test(rt_device_t device)
  36. {
  37. rt_err_t result;
  38. struct rt_device_blk_geometry geometry;
  39. rt_uint8_t * read_buffer = RT_NULL;
  40. rt_uint8_t * write_buffer = RT_NULL;
  41. rt_kprintf("\r\n");
  42. if( (device->flag & RT_DEVICE_FLAG_RDWR) == RT_DEVICE_FLAG_RDWR )
  43. {
  44. // device can read and write.
  45. // step 1: open device
  46. result = rt_device_open(device,RT_DEVICE_FLAG_RDWR);
  47. if( result != RT_EOK )
  48. {
  49. return result;
  50. }
  51. // step 2: get device info
  52. rt_memset(&geometry, 0, sizeof(geometry));
  53. result = rt_device_control(device,
  54. RT_DEVICE_CTRL_BLK_GETGEOME,
  55. &geometry);
  56. if( result != RT_EOK )
  57. {
  58. rt_kprintf("device : %s cmd RT_DEVICE_CTRL_BLK_GETGEOME failed.\r\n");
  59. return result;
  60. }
  61. rt_kprintf("device info:\r\n");
  62. rt_kprintf("sector size : %d byte\r\n", geometry.bytes_per_sector);
  63. rt_kprintf("sector count : %d \r\n", geometry.sector_count);
  64. rt_kprintf("block size : %d byte\r\n", geometry.block_size);
  65. rt_kprintf("\r\n");
  66. read_buffer = rt_malloc(geometry.bytes_per_sector);
  67. if( read_buffer == RT_NULL )
  68. {
  69. rt_kprintf("no memory for read_buffer!\r\n");
  70. goto __return;
  71. }
  72. write_buffer = rt_malloc(geometry.bytes_per_sector);
  73. if( write_buffer == RT_NULL )
  74. {
  75. rt_kprintf("no memory for write_buffer!\r\n");
  76. goto __return;
  77. }
  78. /* step 3: R/W test */
  79. {
  80. rt_uint32_t i, err_count, sector_no;
  81. rt_uint8_t * data_point;
  82. i = rt_device_read(device, 0, read_buffer, 1);
  83. if(i != 1)
  84. {
  85. rt_kprintf("read device :%s ", device->parent.name);
  86. rt_kprintf("the first sector failed.\r\n");
  87. goto __return;
  88. }
  89. data_point = write_buffer;
  90. for(i=0; i<geometry.bytes_per_sector; i++)
  91. {
  92. *data_point++ = (rt_uint8_t)i;
  93. }
  94. /* write first sector */
  95. sector_no = 0;
  96. data_point = write_buffer;
  97. *data_point++ = (rt_uint8_t)sector_no;
  98. i = rt_device_write(device, sector_no, write_buffer,1);
  99. if( i != 1 )
  100. {
  101. rt_kprintf("read the first sector success!\r\n");
  102. rt_kprintf("but write device :%s ", device->parent.name);
  103. rt_kprintf("the first sector failed.\r\n");
  104. rt_kprintf("maybe readonly!\r\n");
  105. goto __return;
  106. }
  107. /* write the second sector */
  108. sector_no = 1;
  109. data_point = write_buffer;
  110. *data_point++ = (rt_uint8_t)sector_no;
  111. i = rt_device_write(device,sector_no,write_buffer,1);
  112. if( i != 1 )
  113. {
  114. rt_kprintf("write device :%s ",device->parent.name);
  115. rt_kprintf("the second sector failed.\r\n");
  116. goto __return;
  117. }
  118. /* write the end sector */
  119. sector_no = geometry.sector_count-1;
  120. data_point = write_buffer;
  121. *data_point++ = (rt_uint8_t)sector_no;
  122. i = rt_device_write(device,sector_no,write_buffer,1);
  123. if( i != 1 )
  124. {
  125. rt_kprintf("write device :%s ",device->parent.name);
  126. rt_kprintf("the end sector failed.\r\n");
  127. goto __return;
  128. }
  129. /* verify first sector */
  130. sector_no = 0;
  131. i = rt_device_read(device,sector_no,read_buffer,1);
  132. if( i != 1 )
  133. {
  134. rt_kprintf("read device :%s ",device->parent.name);
  135. rt_kprintf("the first sector failed.\r\n");
  136. goto __return;
  137. }
  138. err_count = 0;
  139. data_point = read_buffer;
  140. if( (*data_point++) != (rt_uint8_t)sector_no)
  141. {
  142. err_count++;
  143. }
  144. for(i=1; i<geometry.bytes_per_sector; i++)
  145. {
  146. if( (*data_point++) != (rt_uint8_t)i )
  147. {
  148. err_count++;
  149. }
  150. }
  151. if( err_count > 0 )
  152. {
  153. rt_kprintf("verify device :%s ",device->parent.name);
  154. rt_kprintf("the first sector failed.\r\n");
  155. goto __return;
  156. }
  157. /* verify sector sector */
  158. sector_no = 1;
  159. i = rt_device_read(device,sector_no,read_buffer,1);
  160. if( i != 1 )
  161. {
  162. rt_kprintf("read device :%s ",device->parent.name);
  163. rt_kprintf("the second sector failed.\r\n");
  164. goto __return;
  165. }
  166. err_count = 0;
  167. data_point = read_buffer;
  168. if( (*data_point++) != (rt_uint8_t)sector_no)
  169. {
  170. err_count++;
  171. }
  172. for(i=1; i<geometry.bytes_per_sector; i++)
  173. {
  174. if( (*data_point++) != (rt_uint8_t)i )
  175. {
  176. err_count++;
  177. }
  178. }
  179. if( err_count > 0 )
  180. {
  181. rt_kprintf("verify device :%s ",device->parent.name);
  182. rt_kprintf("the second sector failed.\r\n");
  183. goto __return;
  184. }
  185. /* verify the end sector */
  186. sector_no = geometry.sector_count-1;
  187. i = rt_device_read(device,sector_no,read_buffer,1);
  188. if( i != 1 )
  189. {
  190. rt_kprintf("read device :%s ",device->parent.name);
  191. rt_kprintf("the end sector failed.\r\n");
  192. goto __return;
  193. }
  194. err_count = 0;
  195. data_point = read_buffer;
  196. if( (*data_point++) != (rt_uint8_t)sector_no)
  197. {
  198. err_count++;
  199. }
  200. for(i=1; i<geometry.bytes_per_sector; i++)
  201. {
  202. if( (*data_point++) != (rt_uint8_t)i )
  203. {
  204. err_count++;
  205. }
  206. }
  207. if( err_count > 0 )
  208. {
  209. rt_kprintf("verify device :%s ",device->parent.name);
  210. rt_kprintf("the end sector failed.\r\n");
  211. goto __return;
  212. }
  213. rt_kprintf("device R/W test pass!\r\n");
  214. } /* step 3: I/O R/W test */
  215. rt_kprintf("\r\nRT_TICK_PER_SECOND:%d\r\n", RT_TICK_PER_SECOND);
  216. // step 4: continuous single sector speed test
  217. {
  218. rt_uint32_t tick_start,tick_end;
  219. rt_uint32_t i;
  220. rt_kprintf("\r\ncontinuous single sector speed test:\r\n");
  221. if( geometry.sector_count < 10 )
  222. {
  223. rt_kprintf("device sector_count < 10, speed test abort!\r\n");
  224. }
  225. else
  226. {
  227. unsigned int sector;
  228. // sign sector write
  229. rt_kprintf("write: ");
  230. sector = 0;
  231. tick_start = rt_tick_get();
  232. for(i=0; i<200; i++)
  233. {
  234. sector += rt_device_write(device, i, read_buffer, 1);
  235. if((i != 0) && ((i%4) == 0) )
  236. {
  237. if(sector < 4)
  238. {
  239. rt_kprintf("#");
  240. }
  241. else
  242. {
  243. rt_kprintf("<");
  244. }
  245. sector = 0;
  246. }
  247. }
  248. tick_end = rt_tick_get();
  249. rt_kprintf("\r\nwrite 200 sector from %d to %d, ",tick_start,tick_end);
  250. calculate_speed_print( (geometry.bytes_per_sector*200UL*RT_TICK_PER_SECOND)/(tick_end-tick_start) );
  251. rt_kprintf("\r\n");
  252. // sign sector read
  253. rt_kprintf("read : ");
  254. sector = 0;
  255. tick_start = rt_tick_get();
  256. for(i=0; i<200; i++)
  257. {
  258. sector += rt_device_read(device, i, read_buffer, 1);
  259. if((i != 0) && ((i%4) == 0) )
  260. {
  261. if(sector < 4)
  262. {
  263. rt_kprintf("#");
  264. }
  265. else
  266. {
  267. rt_kprintf(">");
  268. }
  269. sector = 0;
  270. }
  271. }
  272. tick_end = rt_tick_get();
  273. rt_kprintf("\r\nread 200 sector from %d to %d, ",tick_start,tick_end);
  274. calculate_speed_print( (geometry.bytes_per_sector*200UL*RT_TICK_PER_SECOND)/(tick_end-tick_start) );
  275. rt_kprintf("\r\n");
  276. }
  277. }// step 4: speed test
  278. // step 5: random single sector speed test
  279. {
  280. rt_uint32_t tick_start,tick_end;
  281. rt_uint32_t i;
  282. rt_kprintf("\r\nrandom single sector speed test:\r\n");
  283. if( geometry.sector_count < 10 )
  284. {
  285. rt_kprintf("device sector_count < 10, speed test abort!\r\n");
  286. }
  287. else
  288. {
  289. unsigned int sector;
  290. // sign sector write
  291. rt_kprintf("write: ");
  292. sector = 0;
  293. tick_start = rt_tick_get();
  294. for(i=0; i<200; i++)
  295. {
  296. sector += rt_device_write(device, (geometry.sector_count / 10) * (i%10) + (i%10), read_buffer, 1);
  297. if((i != 0) && ((i%4) == 0) )
  298. {
  299. if(sector < 4)
  300. {
  301. rt_kprintf("#");
  302. }
  303. else
  304. {
  305. rt_kprintf("<");
  306. }
  307. sector = 0;
  308. }
  309. }
  310. tick_end = rt_tick_get();
  311. rt_kprintf("\r\nwrite 200 sector from %d to %d, ",tick_start,tick_end);
  312. calculate_speed_print( (geometry.bytes_per_sector*200UL*RT_TICK_PER_SECOND)/(tick_end-tick_start) );
  313. rt_kprintf("\r\n");
  314. // sign sector read
  315. rt_kprintf("read : ");
  316. sector = 0;
  317. tick_start = rt_tick_get();
  318. for(i=0; i<200; i++)
  319. {
  320. sector += rt_device_read(device, (geometry.sector_count / 10) * (i%10) + (i%10), read_buffer, 1);
  321. if((i != 0) && ((i%4) == 0) )
  322. {
  323. if(sector < 4)
  324. {
  325. rt_kprintf("#");
  326. }
  327. else
  328. {
  329. rt_kprintf(">");
  330. }
  331. sector = 0;
  332. }
  333. }
  334. tick_end = rt_tick_get();
  335. rt_kprintf("\r\nread 200 sector from %d to %d, ",tick_start,tick_end);
  336. calculate_speed_print( (geometry.bytes_per_sector*200UL*RT_TICK_PER_SECOND)/(tick_end-tick_start) );
  337. rt_kprintf("\r\n");
  338. }
  339. }// step 4: speed test
  340. /* step 6: multiple sector speed test */
  341. {
  342. rt_uint8_t * multiple_buffer;
  343. rt_uint8_t * ptr;
  344. rt_uint32_t tick_start,tick_end;
  345. rt_uint32_t sector,i;
  346. rt_kprintf("\r\nmultiple sector speed test\r\n");
  347. for(sector=2; sector<256; sector=sector*2)
  348. {
  349. multiple_buffer = rt_malloc(geometry.bytes_per_sector * sector);
  350. if(multiple_buffer == RT_NULL)
  351. {
  352. rt_kprintf("no memory for %d sector! multiple sector speed test abort!\r\n", sector);
  353. break;
  354. }
  355. rt_memset(multiple_buffer, sector, geometry.bytes_per_sector * sector);
  356. rt_kprintf("write: ");
  357. tick_start = rt_tick_get();
  358. for(i=0; i<10; i++)
  359. {
  360. rt_size_t n;
  361. n = rt_device_write(device, 50, multiple_buffer, sector);
  362. if(n == sector)
  363. {
  364. rt_kprintf("<");
  365. }
  366. else
  367. {
  368. rt_kprintf("#");
  369. }
  370. }
  371. tick_end = rt_tick_get();
  372. rt_kprintf("\r\n");
  373. rt_kprintf("multiple write %d sector speed : ", sector);
  374. calculate_speed_print( (geometry.bytes_per_sector * sector * 10 * RT_TICK_PER_SECOND)/(tick_end-tick_start) );
  375. rt_kprintf("\r\n");
  376. rt_memset(multiple_buffer, ~sector, geometry.bytes_per_sector * sector);
  377. rt_kprintf("read : ");
  378. tick_start = rt_tick_get();
  379. for(i=0; i<10; i++)
  380. {
  381. rt_size_t n;
  382. n = rt_device_read(device, 50, multiple_buffer, sector);
  383. if(n == sector)
  384. {
  385. rt_kprintf(">");
  386. }
  387. else
  388. {
  389. rt_kprintf("#");
  390. }
  391. }
  392. tick_end = rt_tick_get();
  393. rt_kprintf("\r\n");
  394. rt_kprintf("multiple read %d sector speed : ", sector);
  395. calculate_speed_print( (geometry.bytes_per_sector * sector * 10 * RT_TICK_PER_SECOND)/(tick_end-tick_start) );
  396. ptr = multiple_buffer;
  397. for(i=0; i<geometry.bytes_per_sector * sector; i++)
  398. {
  399. if(*ptr != sector)
  400. {
  401. rt_kprintf(" but data verify fail!");
  402. break;
  403. }
  404. ptr++;
  405. }
  406. rt_kprintf("\r\n\r\n");
  407. rt_free(multiple_buffer);
  408. }
  409. } /* step 5: multiple sector speed test */
  410. rt_device_close(device);
  411. return RT_EOK;
  412. }// device can read and write.
  413. else
  414. {
  415. // device read only
  416. rt_device_close(device);
  417. return RT_EOK;
  418. }// device read only
  419. __return:
  420. if( read_buffer != RT_NULL )
  421. {
  422. rt_free(read_buffer);
  423. }
  424. if( write_buffer != RT_NULL )
  425. {
  426. rt_free(write_buffer);
  427. }
  428. rt_device_close(device);
  429. return RT_ERROR;
  430. }
  431. int device_test(const char * device_name)
  432. {
  433. rt_device_t device = RT_NULL;
  434. // step 1:find device
  435. device = rt_device_find(device_name);
  436. if( device == RT_NULL)
  437. {
  438. rt_kprintf("device %s: not found!\r\n", device_name);
  439. return RT_ERROR;
  440. }
  441. // step 2:init device
  442. if (!(device->flag & RT_DEVICE_FLAG_ACTIVATED))
  443. {
  444. rt_err_t result;
  445. result = rt_device_init(device);
  446. if (result != RT_EOK)
  447. {
  448. rt_kprintf("To initialize device:%s failed. The error code is %d\r\n",
  449. device->parent.name, result);
  450. return result;
  451. }
  452. else
  453. {
  454. device->flag |= RT_DEVICE_FLAG_ACTIVATED;
  455. }
  456. }
  457. // step 3: device test
  458. switch( device->type )
  459. {
  460. case RT_Device_Class_Block :
  461. rt_kprintf("block device!\r\n");
  462. return _block_device_test(device);
  463. default:
  464. rt_kprintf("unkown device type : %02X",device->type);
  465. return RT_ERROR;
  466. }
  467. }
  468. #ifdef RT_USING_FINSH
  469. #include <finsh.h>
  470. FINSH_FUNCTION_EXPORT(device_test, e.g: device_test("sd0"));
  471. #endif