Program to benchmark the speed of the different file system options versus placing data directly into arrays.

Dependencies:   DMBasicGUI DMSupport

This program is used to measure the performance of the different file system options on the LPC4088 Display Module.

The performance wiki page and more specifically the software part describes this program and the output.

As the program doesn't use the display at all it can be used on both the 4.3" and 5" display modules.

Committer:
embeddedartists
Date:
Thu Mar 12 10:24:35 2015 +0100
Revision:
2:ddc1aa3bea3d
Parent:
1:b000ac168e46
Child:
3:1716747cba16
- Added WRITE tests as well

Who changed what in which revision?

UserRevisionLine numberNew contents of line
alindvall 0:b77503796c51 1 /*
alindvall 0:b77503796c51 2 * Copyright 2015 Embedded Artists AB
alindvall 0:b77503796c51 3 *
alindvall 0:b77503796c51 4 * Licensed under the Apache License, Version 2.0 (the "License");
alindvall 0:b77503796c51 5 * you may not use this file except in compliance with the License.
alindvall 0:b77503796c51 6 * You may obtain a copy of the License at
alindvall 0:b77503796c51 7 *
alindvall 0:b77503796c51 8 * http://www.apache.org/licenses/LICENSE-2.0
alindvall 0:b77503796c51 9 *
alindvall 0:b77503796c51 10 * Unless required by applicable law or agreed to in writing, software
alindvall 0:b77503796c51 11 * distributed under the License is distributed on an "AS IS" BASIS,
alindvall 0:b77503796c51 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
alindvall 0:b77503796c51 13 * See the License for the specific language governing permissions and
alindvall 0:b77503796c51 14 * limitations under the License.
alindvall 0:b77503796c51 15 */
alindvall 0:b77503796c51 16
alindvall 0:b77503796c51 17 #include "mbed.h"
alindvall 0:b77503796c51 18 #include "DMBoard.h"
alindvall 0:b77503796c51 19 #include "MCIFileSystem.h"
alindvall 0:b77503796c51 20 #include "QSPIFileSystem.h"
alindvall 0:b77503796c51 21 #include "USBHostMSD.h"
alindvall 0:b77503796c51 22 #include "image_data.h"
alindvall 0:b77503796c51 23 #include "image_data_qspi.h"
alindvall 0:b77503796c51 24
alindvall 0:b77503796c51 25 /******************************************************************************
alindvall 0:b77503796c51 26 * Defines and typedefs
alindvall 0:b77503796c51 27 *****************************************************************************/
alindvall 0:b77503796c51 28
alindvall 0:b77503796c51 29 typedef struct {
alindvall 0:b77503796c51 30 uint32_t size;
alindvall 0:b77503796c51 31 const char* fname;
alindvall 0:b77503796c51 32 const uint8_t* iflash_direct;
alindvall 0:b77503796c51 33 const uint8_t* qspi_direct;
alindvall 0:b77503796c51 34 } bench_input_t;
alindvall 0:b77503796c51 35
alindvall 0:b77503796c51 36 #define NUM_BENCHMARKS (sizeof(BENCHMARK_INPUT)/sizeof(BENCHMARK_INPUT[0]))
alindvall 0:b77503796c51 37
alindvall 0:b77503796c51 38 #define COPYBUF_SIZE (10*1024*1024)
alindvall 0:b77503796c51 39
alindvall 0:b77503796c51 40 #define USBH_CONNECTION_EVENT (1)
alindvall 0:b77503796c51 41
alindvall 0:b77503796c51 42 #define QSPIFS_SIZE_MB (8)
alindvall 0:b77503796c51 43 #define QSPIFS_SIZE (QSPIFS_SIZE_MB * 1024*1024)
alindvall 0:b77503796c51 44
alindvall 0:b77503796c51 45 /******************************************************************************
alindvall 0:b77503796c51 46 * Local variables
alindvall 0:b77503796c51 47 *****************************************************************************/
alindvall 0:b77503796c51 48
alindvall 0:b77503796c51 49 static bench_input_t BENCHMARK_INPUT[] = {
alindvall 0:b77503796c51 50 {
alindvall 0:b77503796c51 51 .size = img_size_bench_600,
alindvall 0:b77503796c51 52 .fname = "bench_600.bmp",
alindvall 0:b77503796c51 53 .iflash_direct = img_bench_600,
alindvall 0:b77503796c51 54 .qspi_direct = qimg_bench_600,
alindvall 0:b77503796c51 55 },
alindvall 0:b77503796c51 56 {
alindvall 0:b77503796c51 57 .size = img_size_bench_10k,
alindvall 0:b77503796c51 58 .fname = "bench_10k.bmp",
alindvall 0:b77503796c51 59 .iflash_direct = img_bench_10k,
alindvall 0:b77503796c51 60 .qspi_direct = qimg_bench_10k,
alindvall 0:b77503796c51 61 },
alindvall 0:b77503796c51 62 {
alindvall 0:b77503796c51 63 .size = img_size_bench_100k,
alindvall 0:b77503796c51 64 .fname = "bench_100k.bmp",
alindvall 0:b77503796c51 65 .iflash_direct = img_bench_100k,
alindvall 0:b77503796c51 66 .qspi_direct = qimg_bench_100k,
alindvall 0:b77503796c51 67 },
alindvall 0:b77503796c51 68 {
alindvall 0:b77503796c51 69 .size = qimg_size_bench_350k,
alindvall 0:b77503796c51 70 .fname = "bench_350k.bmp",
alindvall 0:b77503796c51 71 .iflash_direct = NULL,
alindvall 0:b77503796c51 72 .qspi_direct = qimg_bench_350k,
alindvall 0:b77503796c51 73 },
alindvall 0:b77503796c51 74 {
alindvall 0:b77503796c51 75 .size = qimg_size_bench_1m,
alindvall 0:b77503796c51 76 .fname = "bench_1m.bmp",
alindvall 0:b77503796c51 77 .iflash_direct = NULL,
alindvall 0:b77503796c51 78 .qspi_direct = qimg_bench_1m,
alindvall 0:b77503796c51 79 },
alindvall 0:b77503796c51 80 {
alindvall 0:b77503796c51 81 .size = qimg_size_bench_4m,
alindvall 0:b77503796c51 82 .fname = "bench_4m.bmp",
alindvall 0:b77503796c51 83 .iflash_direct = NULL,
alindvall 0:b77503796c51 84 .qspi_direct = qimg_bench_4m,
alindvall 0:b77503796c51 85 },
alindvall 0:b77503796c51 86 };
alindvall 0:b77503796c51 87
alindvall 0:b77503796c51 88 static MCIFileSystem* mcifs;
alindvall 0:b77503796c51 89 static QSPIFileSystem* qspifs;
alindvall 0:b77503796c51 90 static USBHostMSD* usbmsd;
alindvall 0:b77503796c51 91
alindvall 0:b77503796c51 92 /******************************************************************************
alindvall 0:b77503796c51 93 * Private Functions
alindvall 0:b77503796c51 94 *****************************************************************************/
alindvall 0:b77503796c51 95
alindvall 0:b77503796c51 96
alindvall 0:b77503796c51 97 static bool fileExists(const char* fname) {
alindvall 0:b77503796c51 98 FILE* f = fopen(fname, "r");
alindvall 0:b77503796c51 99 if (f != NULL) {
alindvall 0:b77503796c51 100 fclose(f);
alindvall 0:b77503796c51 101 return true;
alindvall 0:b77503796c51 102 }
alindvall 0:b77503796c51 103 return false;
alindvall 0:b77503796c51 104 }
alindvall 0:b77503796c51 105
alindvall 0:b77503796c51 106 static bool haveAllFiles(const char* prefix) {
alindvall 0:b77503796c51 107 char buff[512] = {0};
alindvall 0:b77503796c51 108 strcpy(buff, prefix);
alindvall 0:b77503796c51 109 int len = strlen(buff);
alindvall 0:b77503796c51 110
alindvall 0:b77503796c51 111 for (int i = 0; i < NUM_BENCHMARKS; i++) {
alindvall 0:b77503796c51 112 strcpy(buff+len, BENCHMARK_INPUT[i].fname);
alindvall 0:b77503796c51 113 if (!fileExists(buff)) {
alindvall 0:b77503796c51 114 DMBoard::instance().logger()->printf("File %s is missing\n", buff);
alindvall 0:b77503796c51 115 return false;
alindvall 0:b77503796c51 116 }
alindvall 0:b77503796c51 117 }
alindvall 0:b77503796c51 118 return true;
alindvall 0:b77503796c51 119 }
alindvall 0:b77503796c51 120
alindvall 0:b77503796c51 121 static bool createFiles(const char* prefix) {
alindvall 0:b77503796c51 122 RtosLog* log = DMBoard::instance().logger();
alindvall 0:b77503796c51 123 char buff[512] = {0};
alindvall 0:b77503796c51 124 strcpy(buff, prefix);
alindvall 0:b77503796c51 125 int len = strlen(buff);
alindvall 0:b77503796c51 126
alindvall 0:b77503796c51 127 for (int i = 0; i < NUM_BENCHMARKS; i++) {
alindvall 0:b77503796c51 128 strcpy(buff+len, BENCHMARK_INPUT[i].fname);
alindvall 0:b77503796c51 129 log->printf(" writing %u bytes to %s\n", BENCHMARK_INPUT[i].size, buff);
alindvall 0:b77503796c51 130 FILE* f = fopen(buff, "w");
alindvall 0:b77503796c51 131 if (f == NULL) {
alindvall 0:b77503796c51 132 log->printf("Failed to create file %s - ABORTING\n", buff);
alindvall 0:b77503796c51 133 return false;
alindvall 0:b77503796c51 134 }
alindvall 0:b77503796c51 135 uint32_t written;
alindvall 0:b77503796c51 136 if (BENCHMARK_INPUT[i].iflash_direct == NULL) {
alindvall 0:b77503796c51 137 // Need to copy from QSPI to SDRAM before attempting to write to the
alindvall 0:b77503796c51 138 // file as it will fail otherwise.
alindvall 0:b77503796c51 139 uint8_t* dest = (uint8_t*)malloc(COPYBUF_SIZE);
alindvall 0:b77503796c51 140 memcpy(dest, BENCHMARK_INPUT[i].qspi_direct, BENCHMARK_INPUT[i].size);
alindvall 0:b77503796c51 141 written = fwrite(dest, 1, BENCHMARK_INPUT[i].size, f);
alindvall 0:b77503796c51 142 free(dest);
alindvall 0:b77503796c51 143 //written = fwrite(BENCHMARK_INPUT[i].qspi_direct, 1, BENCHMARK_INPUT[i].size, f);
alindvall 0:b77503796c51 144 } else {
alindvall 0:b77503796c51 145 written = fwrite(BENCHMARK_INPUT[i].iflash_direct, 1, BENCHMARK_INPUT[i].size, f);
alindvall 0:b77503796c51 146 }
alindvall 0:b77503796c51 147 if (written != BENCHMARK_INPUT[i].size) {
alindvall 0:b77503796c51 148 log->printf("Failed to write %u (only wrote %u) bytes to %s - ABORTING\n", BENCHMARK_INPUT[i].size, written, buff);
embeddedartists 2:ddc1aa3bea3d 149 fclose(f);
alindvall 0:b77503796c51 150 return false;
alindvall 0:b77503796c51 151 }
alindvall 0:b77503796c51 152 fclose(f);
alindvall 0:b77503796c51 153 }
alindvall 0:b77503796c51 154 return true;
alindvall 0:b77503796c51 155 }
alindvall 0:b77503796c51 156
alindvall 0:b77503796c51 157 static bool prepareMCI() {
alindvall 0:b77503796c51 158 RtosLog* log = DMBoard::instance().logger();
alindvall 0:b77503796c51 159 bool ok = false;
alindvall 0:b77503796c51 160
alindvall 0:b77503796c51 161 mcifs = new MCIFileSystem("mci", P4_16);
alindvall 0:b77503796c51 162
alindvall 0:b77503796c51 163 if (mcifs->cardInserted()) {
alindvall 0:b77503796c51 164 log->printf("uSD card detected\n");
alindvall 0:b77503796c51 165
alindvall 0:b77503796c51 166 if (haveAllFiles("/mci/")) {
alindvall 0:b77503796c51 167 log->printf("uSD file system prepared!\n");
alindvall 0:b77503796c51 168 ok = true;
alindvall 0:b77503796c51 169 } else {
alindvall 0:b77503796c51 170 log->printf("One or more files missing, need to (re-)prepare the uSD file system\n");
alindvall 0:b77503796c51 171
alindvall 0:b77503796c51 172 log->printf("Preparing uSD file system...\n");
alindvall 0:b77503796c51 173 if (createFiles("/mci/")) {
alindvall 0:b77503796c51 174 log->printf("uSD file system prepared!\n");
alindvall 0:b77503796c51 175 ok = true;
alindvall 0:b77503796c51 176 } else {
alindvall 0:b77503796c51 177 log->printf("Failed to prepare uSD file system!\n");
alindvall 0:b77503796c51 178 }
alindvall 0:b77503796c51 179 }
alindvall 0:b77503796c51 180 } else {
alindvall 0:b77503796c51 181 log->printf("No uSD card detected. Insert one and reset\n");
alindvall 0:b77503796c51 182 }
alindvall 0:b77503796c51 183
alindvall 0:b77503796c51 184 return ok;
alindvall 0:b77503796c51 185 }
alindvall 0:b77503796c51 186
alindvall 0:b77503796c51 187 static bool prepareUSB() {
alindvall 0:b77503796c51 188 RtosLog* log = DMBoard::instance().logger();
alindvall 0:b77503796c51 189 bool ok = false;
alindvall 0:b77503796c51 190
alindvall 0:b77503796c51 191 usbmsd = new USBHostMSD("usb");
alindvall 0:b77503796c51 192 USBHost* host = USBHost::getHostInst();
alindvall 0:b77503796c51 193 host->signalOnConnections(Thread::gettid(), USBH_CONNECTION_EVENT);
alindvall 0:b77503796c51 194
alindvall 0:b77503796c51 195 log->printf("waiting for connect/disconnect message from USBHost...\n");
alindvall 0:b77503796c51 196 Thread::signal_wait(USBH_CONNECTION_EVENT);
alindvall 0:b77503796c51 197
alindvall 0:b77503796c51 198 if (usbmsd->connect()) {
alindvall 0:b77503796c51 199 log->printf("USB MemoryStick detected\n");
alindvall 0:b77503796c51 200
alindvall 0:b77503796c51 201 if (haveAllFiles("/usb/")) {
alindvall 0:b77503796c51 202 log->printf("USB MemoryStick file system prepared!\n");
alindvall 0:b77503796c51 203 ok = true;
alindvall 0:b77503796c51 204 } else {
alindvall 0:b77503796c51 205 log->printf("One or more files missing, need to (re-)prepare the USB MemoryStick\n");
alindvall 0:b77503796c51 206
alindvall 0:b77503796c51 207 log->printf("Preparing USB MemoryStick file system...\n");
alindvall 0:b77503796c51 208 if (createFiles("/usb/")) {
alindvall 0:b77503796c51 209 log->printf("USB MemoryStick file system prepared!\n");
alindvall 0:b77503796c51 210 ok = true;
alindvall 0:b77503796c51 211 } else {
alindvall 0:b77503796c51 212 log->printf("Failed to prepare USB MemoryStick file system!\n");
alindvall 0:b77503796c51 213 }
alindvall 0:b77503796c51 214 }
alindvall 0:b77503796c51 215 } else {
alindvall 0:b77503796c51 216 log->printf("No USB MemoryStick detected. Insert one and reset\n");
alindvall 0:b77503796c51 217 }
alindvall 0:b77503796c51 218
alindvall 0:b77503796c51 219 return ok;
alindvall 0:b77503796c51 220 }
alindvall 0:b77503796c51 221
alindvall 0:b77503796c51 222 static bool prepareQSPIFS() {
alindvall 0:b77503796c51 223 RtosLog* log = DMBoard::instance().logger();
alindvall 0:b77503796c51 224 bool ok = false;
alindvall 0:b77503796c51 225 bool format = false;
alindvall 0:b77503796c51 226
alindvall 0:b77503796c51 227 qspifs = new QSPIFileSystem("qspi");
alindvall 0:b77503796c51 228
alindvall 0:b77503796c51 229 do {
alindvall 0:b77503796c51 230 if (qspifs->isformatted()) {
alindvall 0:b77503796c51 231 uint32_t start, end;
alindvall 0:b77503796c51 232 qspifs->getMemoryBoundaries(&start, &end);
alindvall 0:b77503796c51 233 if ((end-start) >= QSPIFS_SIZE) {
alindvall 0:b77503796c51 234 log->printf("QSPI file system detected\n");
alindvall 0:b77503796c51 235
alindvall 0:b77503796c51 236 if (haveAllFiles("/qspi/")) {
alindvall 0:b77503796c51 237 log->printf("QSPI file system prepared!\n");
alindvall 0:b77503796c51 238 ok = true;
alindvall 0:b77503796c51 239 break;
alindvall 0:b77503796c51 240 } else {
alindvall 0:b77503796c51 241 log->printf("One or more files missing, need to (re-)prepare the QSPI file system\n");
alindvall 0:b77503796c51 242 }
alindvall 0:b77503796c51 243 } else {
alindvall 0:b77503796c51 244 log->printf("Found too small file system (only %dMB). Formatting...\n", (end-start)/(1024*1024));
alindvall 0:b77503796c51 245 format = true;
alindvall 0:b77503796c51 246 }
alindvall 0:b77503796c51 247 } else {
alindvall 0:b77503796c51 248 log->printf("No QSPI file system detected. Formatting...\n");
alindvall 0:b77503796c51 249 format = true;
alindvall 0:b77503796c51 250 }
alindvall 0:b77503796c51 251
alindvall 0:b77503796c51 252 if (format) {
alindvall 0:b77503796c51 253 if (qspifs->format(QSPIFS_SIZE_MB) == 0) {
alindvall 0:b77503796c51 254 log->printf("Formatting successful\n");
alindvall 0:b77503796c51 255 } else {
alindvall 0:b77503796c51 256 log->printf("Failed to format QSPI file system!\n");
alindvall 0:b77503796c51 257 break;
alindvall 0:b77503796c51 258 }
alindvall 0:b77503796c51 259 }
alindvall 0:b77503796c51 260
alindvall 0:b77503796c51 261 log->printf("Preparing QSPI file system...\n");
alindvall 0:b77503796c51 262 if (createFiles("/qspi/")) {
alindvall 0:b77503796c51 263 log->printf("QSPI file system prepared!\n");
alindvall 0:b77503796c51 264 ok = true;
alindvall 0:b77503796c51 265 } else {
alindvall 0:b77503796c51 266 log->printf("Failed to prepare QSPI file system!\n");
alindvall 0:b77503796c51 267 }
alindvall 0:b77503796c51 268 } while(false);
alindvall 0:b77503796c51 269
alindvall 0:b77503796c51 270 return ok;
alindvall 0:b77503796c51 271 }
alindvall 0:b77503796c51 272
alindvall 0:b77503796c51 273 static bool prepare() {
embeddedartists 1:b000ac168e46 274 RtosLog* log = DMBoard::instance().logger();
embeddedartists 1:b000ac168e46 275
embeddedartists 1:b000ac168e46 276 // make sure that the linker actually placed the data in the
embeddedartists 1:b000ac168e46 277 // correct flashes
embeddedartists 1:b000ac168e46 278 for (int i = 0; i < NUM_BENCHMARKS; i++) {
embeddedartists 1:b000ac168e46 279 if (BENCHMARK_INPUT[i].iflash_direct != NULL) {
embeddedartists 1:b000ac168e46 280 uint32_t tmp = (uint32_t)BENCHMARK_INPUT[i].iflash_direct;
embeddedartists 1:b000ac168e46 281 if ((tmp & 0xff000000) != 0x00000000) {
embeddedartists 1:b000ac168e46 282 log->printf("IFLASH data for benchmark %d is at 0x%08x NOT in IFLASH!! Aborting\n", i, tmp);
embeddedartists 1:b000ac168e46 283 return false;
embeddedartists 1:b000ac168e46 284 }
embeddedartists 1:b000ac168e46 285 tmp = (uint32_t)BENCHMARK_INPUT[i].qspi_direct;
embeddedartists 1:b000ac168e46 286 if ((tmp & 0xff000000) != 0x28000000) {
embeddedartists 1:b000ac168e46 287 log->printf("QSPI data for benchmark %d is at 0x%08x NOT in QSPI!! Aborting\n", i, tmp);
embeddedartists 1:b000ac168e46 288 return false;
embeddedartists 1:b000ac168e46 289 }
embeddedartists 1:b000ac168e46 290 }
embeddedartists 1:b000ac168e46 291 }
alindvall 0:b77503796c51 292 return prepareMCI() && prepareUSB() && prepareQSPIFS();
alindvall 0:b77503796c51 293 }
alindvall 0:b77503796c51 294
alindvall 0:b77503796c51 295 static void readFile(const char* fname, uint8_t* dest) {
alindvall 0:b77503796c51 296 FILE* f = fopen(fname, "r");
alindvall 0:b77503796c51 297 if (f != NULL) {
alindvall 0:b77503796c51 298 int num = fread(dest, 1, 1024, f);
alindvall 0:b77503796c51 299 while (num > 0) {
alindvall 0:b77503796c51 300 dest+=num;
alindvall 0:b77503796c51 301 num = fread(dest, 1, 1024, f);
alindvall 0:b77503796c51 302 }
alindvall 0:b77503796c51 303 fclose(f);
alindvall 0:b77503796c51 304 }
alindvall 0:b77503796c51 305 }
alindvall 0:b77503796c51 306
embeddedartists 2:ddc1aa3bea3d 307 static void runReadBenchmarks() {
alindvall 0:b77503796c51 308 RtosLog* log = DMBoard::instance().logger();
alindvall 0:b77503796c51 309 uint32_t times[NUM_BENCHMARKS][5] = {0};
alindvall 0:b77503796c51 310 uint32_t tmp;
alindvall 0:b77503796c51 311 char buff[512];
alindvall 0:b77503796c51 312 Timer t;
alindvall 0:b77503796c51 313 uint8_t* dest = (uint8_t*)malloc(COPYBUF_SIZE);
alindvall 0:b77503796c51 314 if (dest == NULL) {
alindvall 0:b77503796c51 315 log->printf("Failed to allocate 10MBytes as buffer\n");
alindvall 0:b77503796c51 316 return;
alindvall 0:b77503796c51 317 }
alindvall 0:b77503796c51 318
alindvall 0:b77503796c51 319 t.start();
alindvall 0:b77503796c51 320
alindvall 0:b77503796c51 321 for (int i = 0; i < NUM_BENCHMARKS; i++) {
alindvall 0:b77503796c51 322 // MCI
alindvall 0:b77503796c51 323 sprintf(buff, "/mci/%s", BENCHMARK_INPUT[i].fname);
alindvall 0:b77503796c51 324 memset(dest, 0, COPYBUF_SIZE);
alindvall 0:b77503796c51 325 tmp = t.read_us();
alindvall 0:b77503796c51 326 readFile(buff, dest);
alindvall 0:b77503796c51 327 times[i][0] = t.read_us() - tmp;
alindvall 0:b77503796c51 328 log->printf("Benchmarking %-25s took %8uus\n", buff, times[i][0]);
alindvall 0:b77503796c51 329
alindvall 0:b77503796c51 330 //USB
alindvall 0:b77503796c51 331 sprintf(buff, "/usb/%s", BENCHMARK_INPUT[i].fname);
alindvall 0:b77503796c51 332 memset(dest, 0, COPYBUF_SIZE);
alindvall 0:b77503796c51 333 tmp = t.read_us();
alindvall 0:b77503796c51 334 readFile(buff, dest);
alindvall 0:b77503796c51 335 times[i][1] = t.read_us() - tmp;
alindvall 0:b77503796c51 336 log->printf("Benchmarking %-25s took %8uus\n", buff, times[i][1]);
alindvall 0:b77503796c51 337
alindvall 0:b77503796c51 338 //QSPIFS
alindvall 0:b77503796c51 339 sprintf(buff, "/qspi/%s", BENCHMARK_INPUT[i].fname);
alindvall 0:b77503796c51 340 memset(dest, 0, COPYBUF_SIZE);
alindvall 0:b77503796c51 341 tmp = t.read_us();
alindvall 0:b77503796c51 342 readFile(buff, dest);
alindvall 0:b77503796c51 343 times[i][2] = t.read_us() - tmp;
alindvall 0:b77503796c51 344 log->printf("Benchmarking %-25s took %8uus\n", buff, times[i][2]);
alindvall 0:b77503796c51 345
alindvall 0:b77503796c51 346 //IFLASH
alindvall 0:b77503796c51 347 sprintf(buff, "IFLASH /%s", BENCHMARK_INPUT[i].fname);
alindvall 0:b77503796c51 348 if (BENCHMARK_INPUT[i].iflash_direct != NULL) {
alindvall 0:b77503796c51 349 memset(dest, 0, COPYBUF_SIZE);
alindvall 0:b77503796c51 350 tmp = t.read_us();
alindvall 0:b77503796c51 351 memcpy(dest, BENCHMARK_INPUT[i].iflash_direct, BENCHMARK_INPUT[i].size);
alindvall 0:b77503796c51 352 times[i][3] = t.read_us() - tmp;
alindvall 0:b77503796c51 353 log->printf("Benchmarking %-25s took %8uus\n", buff, times[i][3]);
alindvall 0:b77503796c51 354 } else {
alindvall 0:b77503796c51 355 log->printf("Benchmarking %-25s skipped\n", buff);
alindvall 0:b77503796c51 356 }
alindvall 0:b77503796c51 357
alindvall 0:b77503796c51 358 //QSPI
alindvall 0:b77503796c51 359 sprintf(buff, "QSPI /%s", BENCHMARK_INPUT[i].fname);
alindvall 0:b77503796c51 360 if (BENCHMARK_INPUT[i].qspi_direct != NULL) {
alindvall 0:b77503796c51 361 memset(dest, 0, COPYBUF_SIZE);
alindvall 0:b77503796c51 362 tmp = t.read_us();
alindvall 0:b77503796c51 363 memcpy(dest, BENCHMARK_INPUT[i].qspi_direct, BENCHMARK_INPUT[i].size);
alindvall 0:b77503796c51 364 times[i][4] = t.read_us() - tmp;
alindvall 0:b77503796c51 365 log->printf("Benchmarking %-25s took %8uus\n", buff, times[i][4]);
alindvall 0:b77503796c51 366 } else {
alindvall 0:b77503796c51 367 log->printf("Benchmarking %-25s skipped\n", buff);
alindvall 0:b77503796c51 368 }
alindvall 0:b77503796c51 369 }
alindvall 0:b77503796c51 370
alindvall 0:b77503796c51 371 log->printf("\n\n----\nSummary:\n");
alindvall 0:b77503796c51 372
alindvall 0:b77503796c51 373 log->printf("\n File Information\n");
alindvall 0:b77503796c51 374 log->printf("%18s %10s\n", "Filename", "Size");
alindvall 0:b77503796c51 375 log->printf("%18s %10s\n", "--------", "----");
alindvall 0:b77503796c51 376 for (int i = 0; i < NUM_BENCHMARKS; i++) {
alindvall 0:b77503796c51 377 log->printf("%18s %10d bytes\n", BENCHMARK_INPUT[i].fname, BENCHMARK_INPUT[i].size);
alindvall 0:b77503796c51 378 }
alindvall 0:b77503796c51 379
alindvall 0:b77503796c51 380 log->printf("\n Read times (in us)\n");
alindvall 0:b77503796c51 381 log->printf("%18s %10s %10s %10s %10s %10s\n", "Filename", "uSD Card", "USB", "QSPI FS", "IFLASH[]", "QSPI[]");
alindvall 0:b77503796c51 382 log->printf("%18s %10s %10s %10s %10s %10s\n", "--------", "--------", "---", "-------", "--------", "------");
alindvall 0:b77503796c51 383 for (int i = 0; i < NUM_BENCHMARKS; i++) {
alindvall 0:b77503796c51 384 char* p = (char*)dest;
alindvall 0:b77503796c51 385 for (int x = 0; x < 5; x++) {
alindvall 0:b77503796c51 386 if (times[i][x] == 0) {
alindvall 0:b77503796c51 387 p += sprintf(p, "%10s ", "N/A");
alindvall 0:b77503796c51 388 } else {
alindvall 0:b77503796c51 389 p += sprintf(p, "%10d ", times[i][x]);
alindvall 0:b77503796c51 390 }
alindvall 0:b77503796c51 391 }
alindvall 0:b77503796c51 392 log->printf("%18s %s\n", BENCHMARK_INPUT[i].fname, dest);
alindvall 0:b77503796c51 393 }
alindvall 0:b77503796c51 394
alindvall 0:b77503796c51 395 log->printf("\n Read speeds\n");
alindvall 0:b77503796c51 396 log->printf("%18s %-12s %-12s %-12s %-12s %-12s\n", "Filename", "uSD Card", "USB", "QSPI FS", "IFLASH[]", "QSPI[]");
alindvall 0:b77503796c51 397 log->printf("%18s %s %s %s %s %s\n", "--------", "------------", "------------", "------------", "------------", "------------");
alindvall 0:b77503796c51 398 for (int i = 0; i < NUM_BENCHMARKS; i++) {
alindvall 0:b77503796c51 399 char* p = (char*)dest;
alindvall 0:b77503796c51 400 for (int x = 0; x < 5; x++) {
alindvall 0:b77503796c51 401 if (times[i][x] == 0) {
alindvall 0:b77503796c51 402 p += sprintf(p, "%12s ", "N/A ");
alindvall 0:b77503796c51 403 } else {
alindvall 0:b77503796c51 404 double t = times[i][x];
alindvall 0:b77503796c51 405 double s = BENCHMARK_INPUT[i].size;
alindvall 0:b77503796c51 406 double v = (s*1000000)/t;
alindvall 0:b77503796c51 407 if (v < 10000) {
alindvall 0:b77503796c51 408 p += sprintf(p, "%#7.2F b/s ", v);
alindvall 0:b77503796c51 409 } else if (v < 10000000) {
alindvall 0:b77503796c51 410 p += sprintf(p, "%#7.2F Kb/s ", v/1024.0);
alindvall 0:b77503796c51 411 } else {
alindvall 0:b77503796c51 412 p += sprintf(p, "%#7.2F Mb/s ", v/(1024.0*1024.0));
alindvall 0:b77503796c51 413 }
alindvall 0:b77503796c51 414 }
alindvall 0:b77503796c51 415 }
alindvall 0:b77503796c51 416 log->printf("%18s %s \n", BENCHMARK_INPUT[i].fname, dest);
alindvall 0:b77503796c51 417 }
alindvall 0:b77503796c51 418
alindvall 0:b77503796c51 419 log->printf("\n\n---\n");
embeddedartists 2:ddc1aa3bea3d 420
embeddedartists 2:ddc1aa3bea3d 421 free(dest);
embeddedartists 2:ddc1aa3bea3d 422 }
embeddedartists 2:ddc1aa3bea3d 423
embeddedartists 2:ddc1aa3bea3d 424 static uint32_t writeFile(const char* fname, int benchId, Timer* t, uint8_t* buff) {
embeddedartists 2:ddc1aa3bea3d 425 uint32_t size = BENCHMARK_INPUT[benchId].size;
embeddedartists 2:ddc1aa3bea3d 426
embeddedartists 2:ddc1aa3bea3d 427 // For uSD cards it is not possible to read the data from QSPI flash.
embeddedartists 2:ddc1aa3bea3d 428 // To make all tests equal all source data is copied to external SDRAM
embeddedartists 2:ddc1aa3bea3d 429 // and from there to the destination file. Only the time from SDRAM to
embeddedartists 2:ddc1aa3bea3d 430 // file is meassured.
embeddedartists 2:ddc1aa3bea3d 431 if (BENCHMARK_INPUT[benchId].iflash_direct == NULL) {
embeddedartists 2:ddc1aa3bea3d 432 memcpy(buff, BENCHMARK_INPUT[benchId].qspi_direct, size);
embeddedartists 2:ddc1aa3bea3d 433 } else {
embeddedartists 2:ddc1aa3bea3d 434 memcpy(buff, BENCHMARK_INPUT[benchId].iflash_direct, size);
embeddedartists 2:ddc1aa3bea3d 435 }
embeddedartists 2:ddc1aa3bea3d 436
embeddedartists 2:ddc1aa3bea3d 437 uint32_t time = t->read_us();
embeddedartists 2:ddc1aa3bea3d 438 int written = 0;
embeddedartists 2:ddc1aa3bea3d 439 FILE* f = fopen(fname, "w");
embeddedartists 2:ddc1aa3bea3d 440 if (f != NULL) {
embeddedartists 2:ddc1aa3bea3d 441 written = fwrite(buff, 1, size, f);
embeddedartists 2:ddc1aa3bea3d 442 fclose(f);
embeddedartists 2:ddc1aa3bea3d 443 }
embeddedartists 2:ddc1aa3bea3d 444 if (written == size) {
embeddedartists 2:ddc1aa3bea3d 445 return t->read_us() - time;
embeddedartists 2:ddc1aa3bea3d 446 } else {
embeddedartists 2:ddc1aa3bea3d 447 DMBoard::instance().logger()->printf("Failed to write %s (only wrote %u of %u bytes). Aborting\n", fname, written, size);
embeddedartists 2:ddc1aa3bea3d 448 return 0;
embeddedartists 2:ddc1aa3bea3d 449 }
embeddedartists 2:ddc1aa3bea3d 450 }
embeddedartists 2:ddc1aa3bea3d 451
embeddedartists 2:ddc1aa3bea3d 452 static void runWriteBenchmarks() {
embeddedartists 2:ddc1aa3bea3d 453 RtosLog* log = DMBoard::instance().logger();
embeddedartists 2:ddc1aa3bea3d 454 uint32_t times[NUM_BENCHMARKS][3] = {0};
embeddedartists 2:ddc1aa3bea3d 455 char buff[512];
embeddedartists 2:ddc1aa3bea3d 456 Timer t;
embeddedartists 2:ddc1aa3bea3d 457
embeddedartists 2:ddc1aa3bea3d 458 // For uSD cards it is not possible to read the data from QSPI flash.
embeddedartists 2:ddc1aa3bea3d 459 // To make all tests equal all source data is copied to external SDRAM
embeddedartists 2:ddc1aa3bea3d 460 // and from there to the destination file. Only the time from SDRAM to
embeddedartists 2:ddc1aa3bea3d 461 // file is meassured.
embeddedartists 2:ddc1aa3bea3d 462 uint8_t* dest = (uint8_t*)malloc(COPYBUF_SIZE);
embeddedartists 2:ddc1aa3bea3d 463 if (dest == NULL) {
embeddedartists 2:ddc1aa3bea3d 464 log->printf("Failed to allocate 10MBytes as buffer\n");
embeddedartists 2:ddc1aa3bea3d 465 return;
embeddedartists 2:ddc1aa3bea3d 466 }
embeddedartists 2:ddc1aa3bea3d 467
embeddedartists 2:ddc1aa3bea3d 468 // Clear the entire QSPI file system
embeddedartists 2:ddc1aa3bea3d 469 if (qspifs->format(QSPIFS_SIZE_MB) == 0) {
embeddedartists 2:ddc1aa3bea3d 470 log->printf("Formatting successful\n");
embeddedartists 2:ddc1aa3bea3d 471 } else {
embeddedartists 2:ddc1aa3bea3d 472 log->printf("Failed to format QSPI file system!\n");
embeddedartists 2:ddc1aa3bea3d 473 return;
embeddedartists 2:ddc1aa3bea3d 474 }
embeddedartists 2:ddc1aa3bea3d 475
embeddedartists 2:ddc1aa3bea3d 476 // For uSD and USB formatting is a bad idea as the memory
embeddedartists 2:ddc1aa3bea3d 477 // might contain other important file. Just delete the files
embeddedartists 2:ddc1aa3bea3d 478 // we are using instead.
embeddedartists 2:ddc1aa3bea3d 479 for (int i = 0; i < NUM_BENCHMARKS; i++) {
embeddedartists 2:ddc1aa3bea3d 480 // MCI
embeddedartists 2:ddc1aa3bea3d 481 sprintf(buff, "/mci/%s", BENCHMARK_INPUT[i].fname);
embeddedartists 2:ddc1aa3bea3d 482 remove(buff);
embeddedartists 2:ddc1aa3bea3d 483
embeddedartists 2:ddc1aa3bea3d 484 //USB
embeddedartists 2:ddc1aa3bea3d 485 sprintf(buff, "/usb/%s", BENCHMARK_INPUT[i].fname);
embeddedartists 2:ddc1aa3bea3d 486 remove(buff);
embeddedartists 2:ddc1aa3bea3d 487 }
embeddedartists 2:ddc1aa3bea3d 488
embeddedartists 2:ddc1aa3bea3d 489 t.start();
embeddedartists 2:ddc1aa3bea3d 490
embeddedartists 2:ddc1aa3bea3d 491 // Do the benchmarking
embeddedartists 2:ddc1aa3bea3d 492 for (int i = 0; i < NUM_BENCHMARKS; i++) {
embeddedartists 2:ddc1aa3bea3d 493 // MCI
embeddedartists 2:ddc1aa3bea3d 494 sprintf(buff, "/mci/%s", BENCHMARK_INPUT[i].fname);
embeddedartists 2:ddc1aa3bea3d 495 memset(dest, 0, COPYBUF_SIZE);
embeddedartists 2:ddc1aa3bea3d 496 times[i][0] = writeFile(buff, i, &t, dest);
embeddedartists 2:ddc1aa3bea3d 497 log->printf("Benchmarking %-25s took %8uus\n", buff, times[i][0]);
embeddedartists 2:ddc1aa3bea3d 498
embeddedartists 2:ddc1aa3bea3d 499 //USB
embeddedartists 2:ddc1aa3bea3d 500 sprintf(buff, "/usb/%s", BENCHMARK_INPUT[i].fname);
embeddedartists 2:ddc1aa3bea3d 501 memset(dest, 0, COPYBUF_SIZE);
embeddedartists 2:ddc1aa3bea3d 502 times[i][1] = writeFile(buff, i, &t, dest);
embeddedartists 2:ddc1aa3bea3d 503 log->printf("Benchmarking %-25s took %8uus\n", buff, times[i][1]);
embeddedartists 2:ddc1aa3bea3d 504
embeddedartists 2:ddc1aa3bea3d 505 //QSPIFS
embeddedartists 2:ddc1aa3bea3d 506 sprintf(buff, "/qspi/%s", BENCHMARK_INPUT[i].fname);
embeddedartists 2:ddc1aa3bea3d 507 memset(dest, 0, COPYBUF_SIZE);
embeddedartists 2:ddc1aa3bea3d 508 times[i][2] = writeFile(buff, i, &t, dest);
embeddedartists 2:ddc1aa3bea3d 509 log->printf("Benchmarking %-25s took %8uus\n", buff, times[i][2]);
embeddedartists 2:ddc1aa3bea3d 510 }
embeddedartists 2:ddc1aa3bea3d 511
embeddedartists 2:ddc1aa3bea3d 512 log->printf("\n\n----\nSummary:\n");
embeddedartists 2:ddc1aa3bea3d 513
embeddedartists 2:ddc1aa3bea3d 514 log->printf("\n File Information\n");
embeddedartists 2:ddc1aa3bea3d 515 log->printf("%18s %10s\n", "Filename", "Size");
embeddedartists 2:ddc1aa3bea3d 516 log->printf("%18s %10s\n", "--------", "----");
embeddedartists 2:ddc1aa3bea3d 517 for (int i = 0; i < NUM_BENCHMARKS; i++) {
embeddedartists 2:ddc1aa3bea3d 518 log->printf("%18s %10d bytes\n", BENCHMARK_INPUT[i].fname, BENCHMARK_INPUT[i].size);
embeddedartists 2:ddc1aa3bea3d 519 }
embeddedartists 2:ddc1aa3bea3d 520
embeddedartists 2:ddc1aa3bea3d 521 log->printf("\n Write times (in us)\n");
embeddedartists 2:ddc1aa3bea3d 522 log->printf("%18s %10s %10s %10s\n", "Filename", "uSD Card", "USB", "QSPI FS");
embeddedartists 2:ddc1aa3bea3d 523 log->printf("%18s %10s %10s %10s\n", "--------", "--------", "---", "-------");
embeddedartists 2:ddc1aa3bea3d 524 for (int i = 0; i < NUM_BENCHMARKS; i++) {
embeddedartists 2:ddc1aa3bea3d 525 char* p = (char*)dest;
embeddedartists 2:ddc1aa3bea3d 526 for (int x = 0; x < 3; x++) {
embeddedartists 2:ddc1aa3bea3d 527 if (times[i][x] == 0) {
embeddedartists 2:ddc1aa3bea3d 528 p += sprintf(p, "%10s ", "N/A");
embeddedartists 2:ddc1aa3bea3d 529 } else {
embeddedartists 2:ddc1aa3bea3d 530 p += sprintf(p, "%10d ", times[i][x]);
embeddedartists 2:ddc1aa3bea3d 531 }
embeddedartists 2:ddc1aa3bea3d 532 }
embeddedartists 2:ddc1aa3bea3d 533 log->printf("%18s %s\n", BENCHMARK_INPUT[i].fname, dest);
embeddedartists 2:ddc1aa3bea3d 534 }
embeddedartists 2:ddc1aa3bea3d 535
embeddedartists 2:ddc1aa3bea3d 536 log->printf("\n Write speeds\n");
embeddedartists 2:ddc1aa3bea3d 537 log->printf("%18s %-12s %-12s %-12s\n", "Filename", "uSD Card", "USB", "QSPI FS");
embeddedartists 2:ddc1aa3bea3d 538 log->printf("%18s %s %s %s\n", "--------", "------------", "------------", "------------");
embeddedartists 2:ddc1aa3bea3d 539 for (int i = 0; i < NUM_BENCHMARKS; i++) {
embeddedartists 2:ddc1aa3bea3d 540 char* p = (char*)dest;
embeddedartists 2:ddc1aa3bea3d 541 for (int x = 0; x < 3; x++) {
embeddedartists 2:ddc1aa3bea3d 542 if (times[i][x] == 0) {
embeddedartists 2:ddc1aa3bea3d 543 p += sprintf(p, "%12s ", "N/A ");
embeddedartists 2:ddc1aa3bea3d 544 } else {
embeddedartists 2:ddc1aa3bea3d 545 double t = times[i][x];
embeddedartists 2:ddc1aa3bea3d 546 double s = BENCHMARK_INPUT[i].size;
embeddedartists 2:ddc1aa3bea3d 547 double v = (s*1000000)/t;
embeddedartists 2:ddc1aa3bea3d 548 if (v < 10000) {
embeddedartists 2:ddc1aa3bea3d 549 p += sprintf(p, "%#7.2F b/s ", v);
embeddedartists 2:ddc1aa3bea3d 550 } else if (v < 10000000) {
embeddedartists 2:ddc1aa3bea3d 551 p += sprintf(p, "%#7.2F Kb/s ", v/1024.0);
embeddedartists 2:ddc1aa3bea3d 552 } else {
embeddedartists 2:ddc1aa3bea3d 553 p += sprintf(p, "%#7.2F Mb/s ", v/(1024.0*1024.0));
embeddedartists 2:ddc1aa3bea3d 554 }
embeddedartists 2:ddc1aa3bea3d 555 }
embeddedartists 2:ddc1aa3bea3d 556 }
embeddedartists 2:ddc1aa3bea3d 557 log->printf("%18s %s \n", BENCHMARK_INPUT[i].fname, dest);
embeddedartists 2:ddc1aa3bea3d 558 }
embeddedartists 2:ddc1aa3bea3d 559
embeddedartists 2:ddc1aa3bea3d 560 log->printf("\n\n---\n");
embeddedartists 2:ddc1aa3bea3d 561
embeddedartists 2:ddc1aa3bea3d 562 free(dest);
alindvall 0:b77503796c51 563 }
alindvall 0:b77503796c51 564
alindvall 0:b77503796c51 565 /******************************************************************************
alindvall 0:b77503796c51 566 * Main
alindvall 0:b77503796c51 567 *****************************************************************************/
alindvall 0:b77503796c51 568
alindvall 0:b77503796c51 569 int main()
alindvall 0:b77503796c51 570 {
alindvall 0:b77503796c51 571 DMBoard::BoardError err;
alindvall 0:b77503796c51 572 DMBoard* board = &DMBoard::instance();
alindvall 0:b77503796c51 573 RtosLog* log = board->logger();
alindvall 0:b77503796c51 574
alindvall 0:b77503796c51 575 do {
alindvall 0:b77503796c51 576 err = board->init();
alindvall 0:b77503796c51 577 if (err != DMBoard::Ok) {
alindvall 0:b77503796c51 578 log->printf("Failed to initialize the board, got error %d\r\n", err);
alindvall 0:b77503796c51 579 break;
alindvall 0:b77503796c51 580 }
alindvall 0:b77503796c51 581
alindvall 0:b77503796c51 582 log->printf("\n\nBenchmarking. (Built "__DATE__" at "__TIME__")\n\n");
alindvall 0:b77503796c51 583
alindvall 0:b77503796c51 584 log->printf("Preparing file systems for benchmarking\n");
alindvall 0:b77503796c51 585 if (!prepare()) {
alindvall 0:b77503796c51 586 log->printf("Failed to prepare for benchmarking\r\n");
alindvall 0:b77503796c51 587 break;
alindvall 0:b77503796c51 588 }
alindvall 0:b77503796c51 589
embeddedartists 2:ddc1aa3bea3d 590 runReadBenchmarks();
embeddedartists 2:ddc1aa3bea3d 591
embeddedartists 2:ddc1aa3bea3d 592 Thread::wait(1000);
embeddedartists 2:ddc1aa3bea3d 593 log->printf("Press the USER button to run WRITE tests!\n");
embeddedartists 2:ddc1aa3bea3d 594 while(!board->buttonPressed()) {
embeddedartists 2:ddc1aa3bea3d 595 Thread::wait(20);
embeddedartists 2:ddc1aa3bea3d 596 }
embeddedartists 2:ddc1aa3bea3d 597 while(board->buttonPressed()) {
embeddedartists 2:ddc1aa3bea3d 598 Thread::wait(20);
embeddedartists 2:ddc1aa3bea3d 599 }
embeddedartists 2:ddc1aa3bea3d 600
embeddedartists 2:ddc1aa3bea3d 601 runWriteBenchmarks();
alindvall 0:b77503796c51 602
alindvall 0:b77503796c51 603 } while(false);
alindvall 0:b77503796c51 604
alindvall 0:b77503796c51 605 if (err != DMBoard::Ok) {
alindvall 0:b77503796c51 606 log->printf("\nTERMINATING\n");
alindvall 0:b77503796c51 607 }
alindvall 0:b77503796c51 608
alindvall 0:b77503796c51 609 while(true) {
alindvall 0:b77503796c51 610 Thread::wait(1000);
alindvall 0:b77503796c51 611 }
alindvall 0:b77503796c51 612 }
alindvall 0:b77503796c51 613