LPCOpen Platform  v1.03
LPCOpen Platform for NXP LPC Microcontrollers
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
sdmmc.c
Go to the documentation of this file.
1 /*
2  * @brief SD/MMC 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 #include "rtc.h"
36 #include "ff.h"
37 
76 /*****************************************************************************
77  * Private types/enumerations/variables
78  ****************************************************************************/
79 #ifdef BOARD_HITEX_EVA_18504350
80 #define debugstr(str) board_uart_out_string(str)
81 #else
82 #define debugstr(str) DEBUGSTR(str)
83 #endif
84 
85 /* buffer size (in byte) for R/W operations */
86 #define BUFFER_SIZE 4096
87 
88 static FATFS Fatfs; /* File system object */
89 static FIL Fil; /* File object */
91 
92 static volatile UINT Timer = 0; /* Performance timer (1kHz increment) */
93 static volatile int32_t sdio_wait_exit = 0;
94 
95 /*****************************************************************************
96  * Public types/enumerations/variables
97  ****************************************************************************/
98 
99 /* SDMMC card info structure */
101 
102 /*****************************************************************************
103  * Private functions
104  ****************************************************************************/
105 
106 /* Delay callback for timed SDIF/SDMMC functions */
107 static void sdmmc_waitms(uint32_t time)
108 {
109  /* In an RTOS, the thread would sleep allowing other threads to run.
110  For standalone operation, we just spin on RI timer */
111  int32_t curr = (int32_t) Chip_RIT_GetCounter(LPC_RITIMER);
112  int32_t final = curr + ((SystemCoreClock / 1000) * time);
113 
114  if (final == curr) return;
115 
116  if ((final < 0) && (curr > 0)) {
117  while (Chip_RIT_GetCounter(LPC_RITIMER) < (uint32_t) final) {}
118  }
119  else {
120  while ((int32_t) Chip_RIT_GetCounter(LPC_RITIMER) < final) {}
121  }
122 
123  return;
124 }
125 
131 static void sdmmc_setup_wakeup(void *bits)
132 {
133  uint32_t bit_mask = *((uint32_t *)bits);
134  /* Wait for IRQ - for an RTOS, you would pend on an event here with a IRQ based wakeup. */
135  NVIC_ClearPendingIRQ(SDIO_IRQn);
136  sdio_wait_exit = 0;
137  Chip_SDIF_SetIntMask(LPC_SDMMC, bit_mask);
138  NVIC_EnableIRQ(SDIO_IRQn);
139 }
140 
146 {
148 
149  /* Wait for event, would be nice to have a timeout, but keep it simple */
150  while (sdio_wait_exit == 0) {}
151 
152  /* Get status and clear interrupts */
154 
155  return status;
156 }
157 
158 /* Initialize SD/MMC */
159 static void App_SDMMC_Init()
160 {
161  memset(&sdcardinfo, 0, sizeof(sdcardinfo));
164  sdcardinfo.card_info.msdelay_func = sdmmc_waitms;
165 
166  /* SD/MMC initialization */
168 
169  /* The SDIO driver needs to know the SDIO clock rate */
171 }
172 
173 #ifdef BOARD_HITEX_EVA_18504350
174 /* Initialize the UART for debugging */
175 static void board_uart_debug_init(void)
176 {
177  /* Hitex EVA A4 is sharing Uart port 0 and SDIO pin so it is needed to use Uart port 1 */
179  Chip_UART_SetBaud(LPC_UART1, 115200);
181 
182  /* Enable UART Transmit */
184 }
185 
186 /* Sends a character on the UART */
187 static void board_uart_out_ch(char ch)
188 {
189  while (Chip_UART_SendByte(LPC_UART1, (uint8_t) ch) == ERROR) {}
190 }
191 
192 /* Sends a string on the UART */
193 static void board_uart_out_string(char *str)
194 {
195  while (*str != '\0') {
196  board_uart_out_ch(*str++);
197  }
198 }
199 #endif
200 
201 /*****************************************************************************
202  * Public functions
203  ****************************************************************************/
204 
210 void die(FRESULT rc)
211 {
212  DEBUGOUT("Failed with rc=%u.\n", rc);
213 /* for (;; ) {} */
214 }
215 
220 void SDIO_IRQHandler(void)
221 {
222  /* All SD based register handling is done in the callback
223  function. The SDIO interrupt is not enabled as part of this
224  driver and needs to be enabled/disabled in the callbacks or
225  application as needed. This is to allow flexibility with IRQ
226  handling for applicaitons and RTOSes. */
227  /* Set wait exit flag to tell wait function we are ready. In an RTOS,
228  this would trigger wakeup of a thread waiting for the IRQ. */
229  NVIC_DisableIRQ(SDIO_IRQn);
230  sdio_wait_exit = 1;
231 }
232 
237 int main(void)
238 {
239  FRESULT rc; /* Result code */
240  DIR dir; /* Directory object */
241  FILINFO fno; /* File information object */
242  UINT bw, br, i;
243  char debugBuf[64];
244  char *cbuf = (char *) Buff;
245 
246  Board_Init();
247 #ifdef BOARD_HITEX_EVA_18504350
248  board_uart_debug_init();
249 #endif
250 
251  App_SDMMC_Init();
252 
253  /* There is no need to initialize RTC here it is called by fs init
254  but it takes long time hence doing it before calling f_open */
255  debugstr("Initializing RTC (might take few seconds)...");
256  rtc_initialize();
257  debugstr("Done\r\n");
258 
259  debugstr("Hello NXP Semiconductors\r\n\r\n***SDCARD demo***\r\n");
260 
261  NVIC_DisableIRQ(SDIO_IRQn);
262  /* Enable SD/MMC Interrupt */
263  NVIC_EnableIRQ(SDIO_IRQn);
264 
265  f_mount(0, &Fatfs); /* Register volume work area (never fails) */
266 
267  debugstr("Opening MESSAGE.TXT from SD Card...");
268  rc = f_open(&Fil, "MESSAGE.TXT", FA_READ);
269  if (rc) {
270  debugstr("Failed.\r\n");
271  die(rc);
272  }
273  debugstr("Done.\r\n");
274 
275  debugstr("Printing contents of MESSAGE.TXT...\r\n");
276  for (;; ) {
277  /* Read a chunk of file */
278  rc = f_read(&Fil, (void *)cbuf, BUFFER_SIZE, &br);
279  if (rc || !br) {
280  break; /* Error or end of file */
281  }
282  for (i = 0; i < br; i++) /* Type the data */
284  {board_uart_out_ch((char) cbuf[i]); }
285 #else
286  {DEBUGOUT("%c", cbuf[i]); }
287 #endif
288  }
289  if (rc) {
290  die(rc);
291  }
292 
293  debugstr("Close the file.\r\n");
294  rc = f_close(&Fil);
295  if (rc) {
296  die(rc);
297  }
298 
299  debugstr("Create a new file (hello.txt).\r\n");
300  rc = f_open(&Fil, "HELLO.TXT", FA_WRITE | FA_CREATE_ALWAYS);
301  if (rc) {
302  die(rc);
303  }
304 
305  debugstr("Write text data \"Hello world!\" to HELLO.TXT\r\n");
306 
307  rc = f_write(&Fil, "Hello world!\r\n", 14, &bw);
308  if (rc) {
309  die(rc);
310  }
311 
312  sprintf(debugBuf, "%u bytes written.\r\n", bw);
313  debugstr(debugBuf);
314 
315  debugstr("Close the file.\r\n");
316  rc = f_close(&Fil);
317  if (rc) {
318  die(rc);
319  }
320 
321  debugstr("Open root directory.\r\n");
322  rc = f_opendir(&dir, "");
323  if (rc) {
324  die(rc);
325  }
326 
327  debugstr("Directory listing...\r\n");
328  for (;; ) {
329  /* Read a directory item */
330  rc = f_readdir(&dir, &fno);
331  if (rc || !fno.fname[0]) {
332  break; /* Error or end of dir */
333  }
334  if (fno.fattrib & AM_DIR) {
335  sprintf(debugBuf, " <dir> %s\r\n", fno.fname);
336  }
337  else {
338  sprintf(debugBuf, " %8lu %s\r\n", fno.fsize, fno.fname);
339  }
340  debugstr(debugBuf);
341  }
342  if (rc) {
343  die(rc);
344  }
345 
346  debugstr("Test completed.\r\n");
347  for (;; ) {}
348 }
349