LPCOpen Platform  v1.03
LPCOpen Platform for NXP LPC Microcontrollers
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
app_sdmmc_meas.c
Go to the documentation of this file.
1 /*
2  * @brief SD/MMC benchmark example
3  *
4  * @note
5  * Copyright(C) NXP Semiconductors, 2012
6  * All rights reserved.
7  *
8  * @par
9  * Software that is described herein is for illustrative purposes only
10  * which provides customers with programming information regarding the
11  * LPC products. This software is supplied "AS IS" without any warranties of
12  * any kind, and NXP Semiconductors and its licensor disclaim any and
13  * all warranties, express or implied, including all implied warranties of
14  * merchantability, fitness for a particular purpose and non-infringement of
15  * intellectual property rights. NXP Semiconductors assumes no responsibility
16  * or liability for the use of the software, conveys no license or rights under any
17  * patent, copyright, mask work right, or any other intellectual property rights in
18  * or to any products. NXP Semiconductors reserves the right to make changes
19  * in the software without notification. NXP Semiconductors also makes no
20  * representation or warranty that such application will be suitable for the
21  * specified use without further testing or modification.
22  *
23  * @par
24  * Permission to use, copy, modify, and distribute this software and its
25  * documentation is hereby granted, under NXP Semiconductors' and its
26  * licensor's relevant copyrights in the software, without fee, provided that it
27  * is used in conjunction with NXP Semiconductors microcontrollers. This
28  * copyright, permission, and disclaimer notice must appear in all copies of
29  * this code.
30  */
31 
32 #include <string.h>
33 #include "board.h"
34 #include "chip.h"
35 
72 /*****************************************************************************
73  * Private types/enumerations/variables
74  ****************************************************************************/
75  /* Compiler specific attributes */
76 #if defined(__IAR_SYSTEMS_ICC__)
77  #define LOCATE_ATX(x) _Pragma(#x)
78  #define LOCATE_ATXX(x) LOCATE_ATX(location=x)
79  #define LOCATE_AT(x) LOCATE_ATXX(x)
80  #define WEAK_SYMBOL __weak
81 #elif defined(__ARMCC_VERSION)
82  #define LOCATE_AT(x) __attribute__((at(x)))
83  #define WEAK_SYMBOL __attribute__((weak))
84 #elif (defined(__CODE_RED))
85  #define LOCATE_ATX(x) __attribute__((section(".shmem_"#x ",\"aw\",%nobits@")))
86  #define LOCATE_AT(x) LOCATE_ATX(x)
87  #define WEAK_SYMBOL __attribute__((weak))
88 #else
89  #error "Unsupported Compiler/Tool-Chain!"
90 #endif
91 
92 #ifdef BOARD_HITEX_EVA_18504350
93 #define debugstr(str) board_uart_out_string(str)
94 #else
95 #define debugstr(str) DEBUGSTR(str)
96 #endif
97 
98 /* Number of sectors to read/write */
99 #define NUM_SECTORS 2048
100 
101 /* Number of iterations of measurement */
102 #define NUM_ITER 10
103 
104 /* Starting sector number for read/write */
105 #define START_SECTOR 32
106 
107 /* Buffer size (in bytes) for R/W operations */
108 #define BUFFER_SIZE (NUM_SECTORS * MMC_SECTOR_SIZE)
109 
110 /* Buffers to store original data of SD/MMC card.
111  * The data will be stored in this buffer, once read/write measurement
112  * completed, the original contents will be restored into SD/MMC card.
113  * This is done in order avoid corurupting the SD/MMC card
114  */
115 LOCATE_AT(0x28200000) uint32_t Buff_Backup[BUFFER_SIZE/sizeof(uint32_t)];
116 
117 /* Buffers for read/write operation */
118 LOCATE_AT(0x28000000) uint32_t Buff_Rd[BUFFER_SIZE/sizeof(uint32_t)];
119 LOCATE_AT(0x28100000) uint32_t Buff_Wr[BUFFER_SIZE/sizeof(uint32_t)];
120 
121 /* Measurement data */
122 static uint32_t rd_ticks[NUM_ITER];
123 static uint32_t wr_ticks[NUM_ITER];
124 
125 /* SD/MMC card information */
126 /* Number of sectors in SD/MMC card */
127 static int32_t tot_secs;
128 
129 /* SDIO wait flag */
130 static volatile int32_t sdio_wait_exit = 0;
131 
132 /*****************************************************************************
133  * Public types/enumerations/variables
134  ****************************************************************************/
135 
136 /* SDMMC card info structure */
138 
139 /*****************************************************************************
140  * Private functions
141  ****************************************************************************/
142 
143 /* Delay callback for timed SDIF/SDMMC functions */
144 static void sdmmc_waitms(uint32_t time)
145 {
146  /* In an RTOS, the thread would sleep allowing other threads to run.
147  For standalone operation, we just spin on RI timer */
148  int32_t curr = (int32_t) Chip_RIT_GetCounter(LPC_RITIMER);
149  int32_t final = curr + ((SystemCoreClock / 1000) * time);
150 
151  if (final == curr) return;
152 
153  if ((final < 0) && (curr > 0)) {
154  while (Chip_RIT_GetCounter(LPC_RITIMER) < (uint32_t) final) {}
155  }
156  else {
157  while ((int32_t) Chip_RIT_GetCounter(LPC_RITIMER) < final) {}
158  }
159 
160  return;
161 }
162 
168 static void sdmmc_setup_wakeup(void *bits)
169 {
170  uint32_t bit_mask = *((uint32_t *)bits);
171  /* Wait for IRQ - for an RTOS, you would pend on an event here with a IRQ based wakeup. */
172  NVIC_ClearPendingIRQ(SDIO_IRQn);
173  sdio_wait_exit = 0;
174  Chip_SDIF_SetIntMask(LPC_SDMMC, bit_mask);
175  NVIC_EnableIRQ(SDIO_IRQn);
176 }
177 
183 {
185 
186  /* Wait for event, would be nice to have a timeout, but keep it simple */
187  while (sdio_wait_exit == 0) {}
188 
189  /* Get status and clear interrupts */
191 
192  return status;
193 }
194 
195 /* Initialize SD/MMC */
196 static void App_SDMMC_Init()
197 {
198  memset(&sdcardinfo, 0, sizeof(sdcardinfo));
202 
203  /* SD/MMC initialization */
205 
206  /* The SDIO driver needs to know the SDIO clock rate */
208 }
209 
210 /* Buffer initialisation function */
211 static void Prepare_Buffer(uint32_t value)
212 {
213  uint32_t i;
214 
215  for(i = 0; i < (BUFFER_SIZE/sizeof(uint32_t)); i++)
216  {
217  Buff_Rd[i] = 0x0;
218  Buff_Wr[i] = i + value;
219  }
220 }
221 
222 #ifdef BOARD_HITEX_EVA_18504350
223 /* Initialize the UART for debugging */
224 static void board_uart_debug_init(void)
225 {
226  /* Hitex EVA A4 is sharing Uart port 0 and SDIO pin so it is needed to use Uart port 1 */
228  Chip_UART_SetBaud(LPC_UART1, 115200);
230 
231  /* Enable UART Transmit */
233 }
234 
235 /* Sends a character on the UART */
236 static void board_uart_out_ch(char ch)
237 {
238  while (Chip_UART_SendByte(LPC_UART1, (uint8_t) ch) == ERROR) {}
239 }
240 
241 /* Sends a string on the UART */
242 static void board_uart_out_string(char *str)
243 {
244  while (*str != '\0') {
245  board_uart_out_ch(*str++);
246  }
247 }
248 #endif
249 
250 /* Print the result of a data transfer */
251 static void print_meas_data(void)
252 {
253  static char debugBuf[64];
254  uint64_t tot_sum_rd, tot_sum_wr;
255  uint32_t i, rd_ave, wr_ave, rd_time, wr_time;
256  uint32_t clk = SystemCoreClock/1000000;
257 
258  /* Print Number of Interations */
259  debugstr("\r\n=====================\r\n");
260  debugstr("SDMMC Measurements \r\n");
261  debugstr("=====================\r\n");
262  sprintf(debugBuf, "No. of Iterations: %u \r\n", NUM_ITER);
263  debugstr(debugBuf);
264  sprintf(debugBuf, "No. of Sectors for R/W: %u \r\n", NUM_SECTORS);
265  debugstr(debugBuf);
266  sprintf(debugBuf, "Sector size : %u bytes \r\n", MMC_SECTOR_SIZE);
267  debugstr(debugBuf);
268  sprintf(debugBuf, "Data Transferred : %u bytes\r\n", (MMC_SECTOR_SIZE * NUM_SECTORS));
269  debugstr(debugBuf);
270  tot_sum_rd = tot_sum_wr = 0;
271  for(i = 0; i < NUM_ITER; i++) {
272  tot_sum_rd += rd_ticks[i];
273  tot_sum_wr += wr_ticks[i];
274  }
275  rd_ave = tot_sum_rd / NUM_ITER;
276  wr_ave = tot_sum_wr / NUM_ITER;
277  sprintf(debugBuf, "CPU Speed: %lu.%lu MHz\r\n", clk, (SystemCoreClock / 10000) - (clk * 100));
278  debugstr(debugBuf);
279  sprintf(debugBuf, "Ave Ticks for Read: %u \r\n", rd_ave);
280  debugstr(debugBuf);
281  sprintf(debugBuf, "Aver Ticks for Write: %u \r\n", wr_ave);
282  debugstr(debugBuf);
283  rd_time = (rd_ave / clk);
284  wr_time = (wr_ave / clk);
285  sprintf(debugBuf, "READ: Ave Time: %u usecs Ave Speed : %u KB/sec\r\n", rd_time, ((NUM_SECTORS * MMC_SECTOR_SIZE * 1000)/rd_time));
286  debugstr(debugBuf);
287  sprintf(debugBuf, "WRITE:Ave Time: %u usecs Ave Speed : %u KB/sec \r\n", wr_time, ((NUM_SECTORS * MMC_SECTOR_SIZE * 1000)/wr_time));
288  debugstr(debugBuf);
289 }
290 
291 /*****************************************************************************
292  * Public functions
293  ****************************************************************************/
294 
299 void SDIO_IRQHandler(void)
300 {
301  /* All SD based register handling is done in the callback
302  function. The SDIO interrupt is not enabled as part of this
303  driver and needs to be enabled/disabled in the callbacks or
304  application as needed. This is to allow flexibility with IRQ
305  handling for applicaitons and RTOSes. */
306  /* Set wait exit flag to tell wait function we are ready. In an RTOS,
307  this would trigger wakeup of a thread waiting for the IRQ. */
308  NVIC_DisableIRQ(SDIO_IRQn);
309  sdio_wait_exit = 1;
310 }
311 
316 int main(void)
317 {
318  uint32_t rc; /* Result code */
319  int32_t act_read, act_written;
320  uint32_t i, ite_cnt;
321  uint32_t start_time;
322  uint32_t end_time;
323  static char debugBuf[64];
324  uint32_t backup = 0;
325 
326  Board_Init();
327 #ifdef BOARD_HITEX_EVA_18504350
328  board_uart_debug_init();
329 #endif
330 
331  /* Disable SD/MMC interrupt */
332  NVIC_DisableIRQ(SDIO_IRQn);
333 
334  /* Initialise SD/MMC card */
335  App_SDMMC_Init();
336 
337  debugstr("\r\n==============================\r\n");
338  debugstr("SDMMC CARD measurement demo\r\n");
339  debugstr("==============================\r\n");
340 
341  /* Enable SD/MMC Interrupt */
342  NVIC_DisableIRQ(SDIO_IRQn);
343 
344  /* Wait for a card to be inserted (note CD is not on the
345  SDMMC power rail and can be polled without enabling
346  SD slot power */
347  debugstr("\r\nWait till SD/MMC card inserted...\r\n");
349  debugstr("\r\nSD/MMC Card inserted...\r\n");
350 
351  /* Enable slot power */
353 
354  /* Enumerate the SDMMC card once detected.
355  * Note this function may block for a little while. */
357  if (!rc) {
358  debugstr("SD/MMC Card enumeration failed! ..\r\n");
359  goto error_exit;
360  }
361 
362  /* Check if Write Protected */
364  if (rc) {
365  debugstr("SDMMC Card is write protected!, so tests can not continue..\r\n");
366  goto error_exit;
367  }
368 
369  /* Read Card information */
371 
372  /* Make sure that the sectors are withing the card size */
373  if((START_SECTOR + NUM_SECTORS) >= tot_secs) {
374  debugstr("Out of range parameters! ..\r\n");
375  goto error_exit;
376  }
377 
378  /* Take back up of SD/MMC card contents so that
379  * it can be restored so that SD/MMC card is not corrupted
380  */
381  debugstr("\r\nTaking back up of card.. \r\n");
382  act_read = Chip_SDMMC_ReadBlocks(LPC_SDMMC, (void *)Buff_Backup, START_SECTOR, NUM_SECTORS);
383  if(act_read == 0) {
384  debugstr("Taking back up of card failed!.. \r\n");
385  goto error_exit;
386  }
387 
388  ite_cnt = 0;
389  backup = 1;
390  while(ite_cnt < NUM_ITER) {
391  /* Prepare R/W buffers */
392  Prepare_Buffer(ite_cnt);
393 
394  /* Write data to SD/MMC card */
395  start_time = Chip_RIT_GetCounter(LPC_RITIMER);
396  act_written = Chip_SDMMC_WriteBlocks(LPC_SDMMC, (void *)Buff_Wr, START_SECTOR, NUM_SECTORS);
397  end_time = Chip_RIT_GetCounter(LPC_RITIMER);
398  if(act_written == 0) {
399  sprintf(debugBuf, "WriteBlocks failed for Iter: %u! \r\n", ite_cnt);
400  debugstr(debugBuf);
401  goto error_exit;
402  }
403 
404  if(end_time < start_time) {
405  continue;
406  }
407  else {
408  wr_ticks[ite_cnt] = end_time - start_time;
409  }
410 
411  /* Read data from SD/MMC card */
412  start_time = Chip_RIT_GetCounter(LPC_RITIMER);
413  act_written = Chip_SDMMC_ReadBlocks(LPC_SDMMC, (void *)Buff_Rd, START_SECTOR, NUM_SECTORS);
414  end_time = Chip_RIT_GetCounter(LPC_RITIMER);
415  if(act_read == 0) {
416  sprintf(debugBuf, "ReadBlocks failed for Iter: %u! \r\n", ite_cnt);
417  debugstr(debugBuf);
418  goto error_exit;
419  }
420 
421  if(end_time < start_time) {
422  continue;
423  }
424  else {
425  rd_ticks[ite_cnt] = end_time - start_time;
426  }
427 
428  /* Comapre data */
429  for(i = 0; i < (BUFFER_SIZE/sizeof(uint32_t)); i++)
430  {
431  if(Buff_Rd[i] != Buff_Wr[i])
432  {
433  sprintf(debugBuf, "Data mismacth: ind: %u Rd: 0x%x Wr: 0x%x \r\n", i, Buff_Rd[i], Buff_Wr[i]);
434  debugstr(debugBuf);
435  goto error_exit;
436  }
437  }
438  ite_cnt++;
439  }
440 
441  /* Print Measurement onto UART */
442  print_meas_data();
443 
444 error_exit:
445  /* Restore if back up taken */
446  if(backup) {
447  debugstr("\r\nRestoring the contents of SDMMC card... \r\n");
448  act_written = Chip_SDMMC_WriteBlocks(LPC_SDMMC, (void *)Buff_Backup, START_SECTOR, NUM_SECTORS);
449  if(act_written == 0) {
450  debugstr("Restoring contents failed!.. \r\n");
451  }
452  }
453 
454  debugstr("\r\n========================================\r\n");
455  debugstr("SDMMC CARD measurement demo completed\r\n");
456  debugstr("========================================\r\n");
457 
458  /* Wait forever */
459  for (;; ) {}
460 }
461