LPCOpen Platform
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 "board.h"
33 #include "chip.h"
34 #include "fatfs\diskio.h"
35 #include "fatfs\rtc.h"
36 #include "fs_mci.h"
37 #include "fatfs\ff.h"
38 
65 /*****************************************************************************
66  * Private types/enumerations/variables
67  ****************************************************************************/
68 
69 #if _USE_XSTRFUNC == 0
70 #include <string.h>
71 #define xstrlen(x) strlen(x)
72 #define xstrcpy(x, y) strcpy(x, y)
73 #define xmemset(x, y, z) memset(x, y, z)
74 #define xstrchr(x, y) strchr(x, y)
75 #endif
76 
77 #ifdef BOARD_HITEX_EVA_18504350
78 #define debugstr(str) board_uart_out_string(str)
79 #else
80 #define debugstr(str) DEBUGSTR(str)
81 #endif
82 
83 /* buffer size (in byte) for R/W operations */
84 #define BUFFER_SIZE 4096
85 
86 static FATFS Fatfs; /* File system object */
87 static FIL Fil; /* File object */
88 
89 #ifdef __IAR_SYSTEMS_ICC__
90 #pragma data_alignment=4
91 static BYTE Buff[BUFFER_SIZE]; /* Working buffer */
92 #else
93 static BYTE Buff[BUFFER_SIZE] __attribute__ ((aligned(4))); /* Working buffer */
94 #endif
95 
96 static volatile UINT Timer = 0; /* Performance timer (1kHz increment) */
97 static volatile int32_t sdio_wait_exit = 0;
98 static volatile uint32_t u32Milliseconds;
99 static volatile uint32_t timerCntms = 0;
100 
101 #define TIME_INTERVAL 1/* 1ms */
102 
103 /*****************************************************************************
104  * Public types/enumerations/variables
105  ****************************************************************************/
106 
107 /* SDMMC card info structure */
109 
110 /*****************************************************************************
111  * Private functions
112  ****************************************************************************/
113 
114 /* Delay callback for timed SDIF/SDMMC functions */
115 static void sdmmc_waitms(uint32_t time)
116 {
117  /* In an RTOS, the thread would sleep allowing other threads to run. For standalone operation, we just spin on a timer */
118  /* TIM_Waitus(time * 1000); */
119  timerCntms = time;
120  while (timerCntms) {}
121 }
122 
128 static void sdmmc_setup_wakeup(uint32_t bits)
129 {
130  /* Wait for IRQ - for an RTOS, you would pend on an event here with a IRQ based wakeup. */
131  NVIC_ClearPendingIRQ(SDIO_IRQn);
132  sdio_wait_exit = 0;
133  Chip_SDMMC_SetIntMask(bits);
134  NVIC_EnableIRQ(SDIO_IRQn);
135 }
136 
143 {
145 
146  /* Wait for event, would be nice to have a timeout, but keep it simple */
147  while (sdio_wait_exit == 0) {}
148 
149  /* Get status and clear interrupts */
150  status = Chip_SDMMC_GetIntStatus();
151 
152  return status;
153 }
154 
155 /* Initialize the Repetitive Interrupt Timer at 1s */
156 static void App_Timer_Init(void)
157 {
158  Chip_RIT_Init();
159  /* Configure time_interval for RIT
160  * In this case: time_interval = 1000 ms = 1s
161  * So, RIT will generate interrupt each 1s
162  */
164 }
165 
166 /* Initialize SD/MMC */
167 static void App_SDMMC_Init()
168 {
169  memset(&sdcardinfo, 0, sizeof(sdcardinfo));
170  sdcardinfo.evsetup_cb = sdmmc_setup_wakeup;
171  sdcardinfo.waitfunc_cb = sdmmc_irq_driven_wait;
172  sdcardinfo.msdelay_func = sdmmc_waitms;
173 
174  /* SD/MMC initialization */
176 
177  /* The SDIO driver needs to know the SDIO clock rate */
178  Chip_Clock_EnableOpts(CLK_MX_SDIO, true, true, 1);
180  Chip_SDMMC_Init();
181 }
182 
183 #ifdef BOARD_HITEX_EVA_18504350
184 /* Initialize the UART for debugging */
185 static void board_uart_debug_init(void)
186 {
187  /* Hitex EVA A4 is sharing Uart port 0 and SDIO pin so it is needed to use Uart port 1 */
189  Chip_UART_SetBaud(LPC_UART1, 115200);
191 
192  /* Enable UART Transmit */
194 }
195 
196 /* Sends a character on the UART */
197 static void board_uart_out_ch(char ch)
198 {
199  while (Chip_UART_SendByte(LPC_UART1, (uint8_t) ch) == ERROR) {}
200 }
201 
202 /* Sends a string on the UART */
203 static void board_uart_out_string(char *str)
204 {
205  while (*str != '\0') {
206  board_uart_out_ch(*str++);
207  }
208 }
209 #endif
210 
211 /*****************************************************************************
212  * Public functions
213  ****************************************************************************/
214 
220 void die(FRESULT rc)
221 {
222  DEBUGOUT("Failed with rc=%u.\n", rc);
223 // for (;; ) {}
224 }
225 
230 void SysTick_Handler(void)
231 {
232  u32Milliseconds += 10;
233 }
234 
239 void SDIO_IRQHandler(void)
240 {
241  /* All SD based register handling is done in the callback
242  function. The SDIO interrupt is not enabled as part of this
243  driver and needs to be enabled/disabled in the callbacks or
244  application as needed. This is to allow flexibility with IRQ
245  handling for applicaitons and RTOSes. */
246  /* Set wait exit flag to tell wait function we are ready. In an RTOS,
247  this would trigger wakeup of a thread waiting for the IRQ. */
248  NVIC_DisableIRQ(SDIO_IRQn);
249  sdio_wait_exit = 1;
250 }
251 
256 void RIT_IRQHandler(void)
257 {
258  /* Clear interrupt flag */
260 
261  /* Disk timer function (100Hz) */
262  disk_timerproc();
263  if (timerCntms) {
264  timerCntms--;
265  }
266 }
267 
276 {
277  RTC rtc;
278 
279  /* Get local time */
280  rtc_gettime(&rtc);
281 
282  /* Pack date and time into a DWORD variable */
283  return ((DWORD) (rtc.year - 1980) << 25)
284  | ((DWORD) rtc.month << 21)
285  | ((DWORD) rtc.mday << 16)
286  | ((DWORD) rtc.hour << 11)
287  | ((DWORD) rtc.min << 5)
288  | ((DWORD) rtc.sec >> 1);
289 }
290 
295 int main(void)
296 {
297  FRESULT rc; /* Result code */
298  DIR dir; /* Directory object */
299  FILINFO fno; /* File information object */
300  UINT bw, br, i;
301  char debugBuf[64];
302 
303  Board_Init();
304 #ifdef BOARD_HITEX_EVA_18504350
305  board_uart_debug_init();
306 #endif
307 
308  App_SDMMC_Init();
309 
310  /* Initialize Repitetive Timer */
311  App_Timer_Init();
312 
313  debugstr("\n\rHello NXP Semiconductors\n\rSDIO demo");
314 
315  /* Initialize RTC timer */
316  rtc_initialize();
317 
318  NVIC_DisableIRQ(SDIO_IRQn);
319  /* Enable SD/MMC Interrupt */
320  NVIC_EnableIRQ(SDIO_IRQn);
321  /* Enable RIT interrupt */
322  NVIC_EnableIRQ(RITIMER_IRQn);
323 
324  f_mount(0, &Fatfs); /* Register volume work area (never fails) */
325 
326  debugstr("\n\rOpen an existing file (message.txt).\n\r");
327 
328  rc = f_open(&Fil, "MESSAGE.TXT", FA_READ);
329  if (rc) {
330  die(rc);
331  }
332 
333  for (;; ) {
334  /* Read a chunk of file */
335  rc = f_read(&Fil, Buff, sizeof Buff, &br);
336  if (rc || !br) {
337  break; /* Error or end of file */
338  }
339  for (i = 0; i < br; i++) /* Type the data */
341  {board_uart_out_ch((char) Buff[i]); }
342 #else
343  {DEBUGOUT("%c", Buff[i]); }
344 #endif
345  }
346  if (rc) {
347  die(rc);
348  }
349 
350  debugstr("\n\rClose the file.\n");
351  rc = f_close(&Fil);
352  if (rc) {
353  die(rc);
354  }
355 
356  debugstr("\n\rCreate a new file (hello.txt).\n");
357  rc = f_open(&Fil, "HELLO.TXT", FA_WRITE | FA_CREATE_ALWAYS);
358  if (rc) {
359  die(rc);
360  }
361 
362  debugstr("\n\rWrite a text data. (Hello world!)\n");
363 
364  rc = f_write(&Fil, "Hello world!\r\n", 14, &bw);
365  if (rc) {
366  die(rc);
367  }
368 
369  sprintf(debugBuf, "%u bytes written.\n", bw);
370  debugstr(debugBuf);
371 
372  debugstr("\n\rClose the file.\n");
373  rc = f_close(&Fil);
374  if (rc) {
375  die(rc);
376  }
377 
378  debugstr("\n\rOpen root directory.\n");
379  rc = f_opendir(&dir, "");
380  if (rc) {
381  die(rc);
382  }
383 
384  debugstr("\n\rDirectory listing...\n\r");
385  for (;; ) {
386  /* Read a directory item */
387  rc = f_readdir(&dir, &fno);
388  if (rc || !fno.fname[0]) {
389  break; /* Error or end of dir */
390  }
391  if (fno.fattrib & AM_DIR) {
392  sprintf(debugBuf, " <dir> %s\n\r", fno.fname);
393  }
394  else {
395  sprintf(debugBuf, " %8lu %s\n\r", fno.fsize, fno.fname);
396  }
397  debugstr(debugBuf);
398  }
399  if (rc) {
400  die(rc);
401  }
402 
403  debugstr("\n\rTest completed.\n");
404  for (;; ) {}
405 }
406