1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2010 Thomas Martitz, Andree Buschmann
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
26 #if PLUGIN_BUFFER_SIZE <= 0x8000
27 #define BUF_SIZE (1<<12) /* 16 KB = (1<<12)*sizeof(int) */
29 #define BUF_SIZE (1<<13) /* 32 KB = (1<<13)*sizeof(int) */
32 #define LOOP_REPEAT_DRAM 256
33 static int loop_repeat_dram
= LOOP_REPEAT_DRAM
;
34 static volatile int buf_dram
[BUF_SIZE
] MEM_ALIGN_ATTR
;
36 #if defined(PLUGIN_USE_IRAM)
37 #define LOOP_REPEAT_IRAM 256
38 static int loop_repeat_iram
= LOOP_REPEAT_DRAM
;
39 static volatile int buf_iram
[BUF_SIZE
] IBSS_ATTR MEM_ALIGN_ATTR
;
42 /* (Byte per loop * loops)>>20 * ticks per s * 10 / ticks = dMB per s */
43 #define dMB_PER_SEC(buf_size, cnt, delta) ((((buf_size*sizeof(int)*cnt)>>20)*HZ*10)/delta)
45 static void memset_test(volatile int *buf
, int buf_size
, int loop_cnt
)
47 size_t buf_bytes
= buf_size
*sizeof(buf
[0]);
48 for(int i
= 0; i
< loop_cnt
; i
++)
50 memset((void*)buf
, 0xff, buf_bytes
);
54 static void memcpy_test(volatile int *buf
, int buf_size
, int loop_cnt
)
56 /* half-size memcpy since memory regions must not overlap */
57 void* half_buf
= (void*)(&buf
[buf_size
/2]);
58 size_t half_buf_bytes
= buf_size
* sizeof(buf
[0]) / 2;
60 /* double loop count to compensate for half size memcpy */
61 for(int i
= 0; i
< loop_cnt
*2; i
++)
63 memcpy((void*)&buf
[0], half_buf
, half_buf_bytes
);
67 static void write_test(volatile int *buf
, int buf_size
, int loop_cnt
)
76 ".outer_loop_read: \n"
79 ".inner_loop_read: \n"
80 "stmia r4!, {r0-r3} \n"
81 "stmia r4!, {r0-r3} \n"
83 "bgt .inner_loop_read \n"
85 "bgt .outer_loop_read \n"
87 : [loops
] "r" (loop_cnt
), [size
] "r" (buf_size
), [buf_p
] "r" (buf
)
88 : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "memory", "cc"
91 for(int i
= 0; i
< loop_cnt
; i
++)
93 for(int j
= 0; j
< buf_size
; j
+=4)
104 static void read_test(volatile int *buf
, int buf_size
, int loop_cnt
)
108 "mov r6, %[loops] \n"
109 ".outer_loop_write: \n"
110 "mov r4, %[buf_p] \n"
112 ".inner_loop_write: \n"
113 "ldmia r4!, {r0-r3} \n"
115 "ldmia r4!, {r0-r3} \n"
116 "bgt .inner_loop_write \n"
118 "bgt .outer_loop_write \n"
120 : [loops
] "r" (loop_cnt
), [size
] "r" (buf_size
), [buf_p
] "r" (buf
)
121 : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "memory", "cc"
125 for(int i
= 0; i
< loop_cnt
; i
++)
127 for(int j
= 0; j
< buf_size
; j
+=4)
145 static const char tests
[][7] = {
153 #define TEST_MEM_PRINTF(...) rb->screens[0]->putsf(0, line++, __VA_ARGS__)
155 static int test(volatile int *buf
, int buf_size
, int loop_cnt
,
159 int last_tick
= *rb
->current_tick
;
164 case READ
: read_test(buf
, buf_size
, loop_cnt
); break;
165 case WRITE
: write_test(buf
, buf_size
, loop_cnt
); break;
166 case MEMSET
: memset_test(buf
, buf_size
, loop_cnt
); break;
167 case MEMCPY
: memcpy_test(buf
, buf_size
, loop_cnt
); break;
170 delta
= *rb
->current_tick
- last_tick
;
174 /* The loop_cnt will be increased for the next measurement set until
175 * each measurement at least takes 10 ticks. This is to ensure a
176 * minimum accuracy. */
180 delta
= delta
>0 ? delta
: delta
+1;
181 dMB
= dMB_PER_SEC(buf_size
, loop_cnt
, delta
);
182 TEST_MEM_PRINTF("%s: %3d.%d MB/s (%3d ms)",
183 tests
[type
], dMB
/10, dMB
%10, delta
*10);
188 enum plugin_status
plugin_start(const void* parameter
)
192 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
197 #ifdef HAVE_LCD_BITMAP
198 rb
->lcd_setfont(FONT_SYSFIXED
);
201 rb
->screens
[0]->clear_display();
202 TEST_MEM_PRINTF("patience, may take some seconds...");
203 rb
->screens
[0]->update();
209 rb
->screens
[0]->clear_display();
210 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
211 TEST_MEM_PRINTF("%s", boost
?"boosted":"unboosted");
212 TEST_MEM_PRINTF("clock: %d Hz", *rb
->cpu_frequency
);
214 TEST_MEM_PRINTF("loop#: %d", ++count
);
216 TEST_MEM_PRINTF("DRAM cnt: %d size: %d MB", loop_repeat_dram
,
217 (loop_repeat_dram
*BUF_SIZE
*sizeof(buf_dram
[0]))>>20);
219 ret
|= test(buf_dram
, BUF_SIZE
, loop_repeat_dram
, READ
);
220 ret
|= test(buf_dram
, BUF_SIZE
, loop_repeat_dram
, WRITE
);
221 ret
|= test(buf_dram
, BUF_SIZE
, loop_repeat_dram
, MEMSET
);
222 ret
|= test(buf_dram
, BUF_SIZE
, loop_repeat_dram
, MEMCPY
);
223 if (ret
!= 0) loop_repeat_dram
*= 2;
224 #if defined(PLUGIN_USE_IRAM)
225 TEST_MEM_PRINTF("IRAM cnt: %d size: %d MB", loop_repeat_iram
,
226 (loop_repeat_iram
*BUF_SIZE
*sizeof(buf_iram
[0]))>>20);
228 ret
|= test(buf_iram
, BUF_SIZE
, loop_repeat_iram
, READ
);
229 ret
|= test(buf_iram
, BUF_SIZE
, loop_repeat_iram
, WRITE
);
230 ret
|= test(buf_iram
, BUF_SIZE
, loop_repeat_iram
, MEMSET
);
231 ret
|= test(buf_iram
, BUF_SIZE
, loop_repeat_iram
, MEMCPY
);
232 if (ret
!= 0) loop_repeat_iram
*= 2;
235 rb
->screens
[0]->update();
237 switch (rb
->get_action(CONTEXT_STD
, HZ
/5))
239 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
240 case ACTION_STD_PREV
:
248 case ACTION_STD_NEXT
:
251 rb
->cpu_boost(false);
256 case ACTION_STD_CANCEL
: