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