LPCOpen Platform
LPCOpen Platform for NXP LPC Microcontrollers
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
fs_mci.c
Go to the documentation of this file.
1 /*
2  * @brief SDMMC Chan FATFS simple abstraction layer
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 
33 #ifdef CFG_SDCARD
34 
35 #include "fs_mci.h"
36 #include "board.h"
37 #include "chip.h"
38 
39 /*****************************************************************************
40  * Private types/enumerations/variables
41  ****************************************************************************/
42 
43 /* Disk Status */
44 static volatile DSTATUS Stat = STA_NOINIT;
45 
46 /* 100Hz decrement timer stopped at zero (disk_timerproc()) */
47 static volatile WORD Timer2;
48 
49 /* Card Configuration */
50 // CARDCONFIG CardConfig; /* Card configuration */
51 
52 /*****************************************************************************
53  * Public types/enumerations/variables
54  ****************************************************************************/
55 
57 
58 /*****************************************************************************
59  * Private functions
60  ****************************************************************************/
61 
62 /* Get bits from an array */
63 uint32_t unstuff_bits(uint8_t *resp, uint32_t start, uint32_t size)
64 {
65  uint32_t byte_idx_stx;
66  uint8_t bit_idx_stx, bit_idx;
67  uint32_t ret, byte_idx;
68 
69  byte_idx_stx = start / 8;
70  bit_idx_stx = start - byte_idx_stx * 8;
71 
72  if (size < (8 - bit_idx_stx)) {
73  return (resp[byte_idx_stx] >> bit_idx_stx) & ((1 << size) - 1);
74  }
75 
76  ret = 0;
77 
78  ret = (resp[byte_idx_stx] >> bit_idx_stx) & ((1 << (8 - bit_idx_stx)) - 1);
79  bit_idx = 8 - bit_idx_stx;
80  size -= bit_idx;
81 
82  byte_idx = 1;
83  while (size > 8) {
84  ret |= resp[byte_idx_stx + byte_idx] << (bit_idx);
85  size -= 8;
86  bit_idx += 8;
87  byte_idx++;
88  }
89 
90  if (size > 0) {
91  ret |= (resp[byte_idx_stx + byte_idx] & ((1 << size) - 1)) << bit_idx;
92  }
93 
94  return ret;
95 }
96 
97 /* Swap buffer */
98 static void swap_buff(uint8_t *buff, uint32_t count)
99 {
100  uint8_t tmp;
101  uint32_t i;
102 
103  for (i = 0; i < count / 2; i++) {
104  tmp = buff[i];
105  buff[i] = buff[count - i - 1];
106  buff[count - i - 1] = tmp;
107  }
108 }
109 
110 /* Wait for device to complete */
111 bool mci_wait_for_ready(void)
112 {
113  /* Poll card for program completion */
114  Timer2 = 50;// 500 ms
115  while (Timer2) {
116  if (Chip_SDMMC_GetState() != -1) {
117  return true;
118  }
119  }
120 
121  return false;
122 }
123 
124 /*****************************************************************************
125  * Public functions
126  ****************************************************************************/
127 
128 /* Initialize Disk Drive */
130 {
131  if (drv) {
132  return STA_NOINIT; /* Supports only single drive */
133  }
134  // if (Stat & STA_NODISK) return Stat; /* No card in the socket */
135 
136  if (Stat != STA_NOINIT) {
137  return Stat; // card is already enumerated
138 
139  }
140  /* Reset */
141  Stat = STA_NOINIT;
142 
143 #ifndef BOARD_NGX_XPLORER_18304330
144  /* NGX board ignored SD_CD pin */
145  /* Wait for a card to be inserted (note CD is not on the SDMMC power rail and can be polled without enabling SD slot power */
146  while (Chip_SDMMC_CardNDetect() == 0) {}
147 #endif
148 
149  /* Enumerate the card once detected. Note this function may block for a little while. */
150 
151  if (!Chip_SDMMC_Acquire(&sdcardinfo)) {
152  DEBUGOUT("Card Acquire failed...\r\n");
153  return Stat;
154  }
155 
156  Stat &= ~STA_NOINIT;
157  return Stat;
158 
159 }
160 
161 /* Disk Drive miscellaneous Functions */
162 DRESULT disk_ioctl(BYTE drv, BYTE ctrl, void *buff)
163 {
164  DRESULT res;
165  BYTE n, *ptr = buff;
166  ULONG *ptr32 = (ULONG *) buff;
167 
168  if (drv) {
169  return RES_PARERR;
170  }
171  if (Stat & STA_NOINIT) {
172  return RES_NOTRDY;
173  }
174 
175  res = RES_ERROR;
176 
177  switch (ctrl) {
178  case CTRL_SYNC: /* Make sure that no pending write process */
179  if (mci_wait_for_ready() == true) {
180  res = RES_OK;
181  }
182 
183  break;
184 
185  case GET_SECTOR_COUNT: /* Get number of sectors on the disk (DWORD) */
186  *(DWORD *) buff = sdcardinfo.blocknr;
187  res = RES_OK;
188  break;
189 
190  case GET_SECTOR_SIZE: /* Get R/W sector size (WORD) */
191  *(WORD *) buff = sdcardinfo.block_len; // 512;
192  res = RES_OK;
193  break;
194 
195  case GET_BLOCK_SIZE:/* Get erase block size in unit of sector (DWORD) */
196  *(DWORD *) buff = 4096; // FIXED:
197  res = RES_OK;
198  break;
199 
200  case MMC_GET_TYPE: /* Get card type flags (1 byte) */
201  *ptr = sdcardinfo.card_type;
202  res = RES_OK;
203  break;
204 
205  case MMC_GET_CSD: /* Receive CSD as a data block (16 bytes) */
206  for (n = 0; n < 4; n++) {
207  *(ptr32 + n) = sdcardinfo.csd[n];
208  }
209  res = RES_OK;
210  break;
211 
212  case MMC_GET_CID: /* Receive CID as a data block (16 bytes) */
213  for (n = 0; n < 4; n++) {
214  *(ptr32 + n) = sdcardinfo.cid[n];
215  }
216  res = RES_OK;
217  break;
218 
219  case MMC_GET_SDSTAT:/* Receive SD status as a data block (64 bytes) */
220  {
221  int32_t cardStatus;
222 
223  cardStatus = Chip_SDMMC_GetState();
224  if (cardStatus != -1) {
225  uint8_t *status = (uint8_t *) &cardStatus;
226  for (n = 0; n < 2; n++) {
227  *(ptr + n) = ((uint8_t *) status)[n];
228  }
229  res = RES_OK;
230  }
231  }
232  break;
233 
234  default:
235  res = RES_PARERR;
236  break;
237  }
238 
239  return res;
240 }
241 
242 /* Read Sector(s) */
243 DRESULT disk_read(BYTE drv, BYTE *buff, DWORD sector, BYTE count)
244 {
245  if (drv || !count) {
246  return RES_PARERR;
247  }
248  if (Stat & STA_NOINIT) {
249  return RES_NOTRDY;
250  }
251 
252  if (Chip_SDMMC_ReadBlocks(buff, sector, count)) {
253  return RES_OK;
254  }
255 
256  return RES_ERROR;
257 }
258 
259 /* Get Disk Status */
261 {
262  if (drv) {
263  return STA_NOINIT; /* Supports only single drive */
264 
265  }
266  return Stat;
267 }
268 
269 /* Write Sector(s) */
270 DRESULT disk_write(BYTE drv, const BYTE *buff, DWORD sector, BYTE count)
271 {
272 
273  if (drv || !count) {
274  return RES_PARERR;
275  }
276  if (Stat & STA_NOINIT) {
277  return RES_NOTRDY;
278  }
279 
280  if ( Chip_SDMMC_WriteBlocks((void *) buff, sector, count)) {
281  return RES_OK;
282  }
283 
284  return RES_ERROR;
285 }
286 
287 /* Device timer function */
288 void disk_timerproc(void)
289 {
290  WORD n;
291 
292  n = Timer2;
293  if (n) {
294  Timer2 = --n;
295  }
296 }
297 #endif /*CFG_SDCARD*/