LPCOpen Platform  v1.03
LPCOpen Platform for NXP LPC Microcontrollers
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
usbmsdev.c
Go to the documentation of this file.
1 /*
2  * @brief USB Mass Storage Device Dual core 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 "usbmsdev.h"
33 
34 /*****************************************************************************
35  * Private types/enumerations/variables
36  ****************************************************************************/
37 
43  .Config = {
44  .InterfaceNumber = 0,
45 
46  .DataINEndpointNumber = MASS_STORAGE_IN_EPNUM,
47  .DataINEndpointSize = MASS_STORAGE_IO_EPSIZE,
48  .DataINEndpointDoubleBank = false,
49 
50  .DataOUTEndpointNumber = MASS_STORAGE_OUT_EPNUM,
51  .DataOUTEndpointSize = MASS_STORAGE_IO_EPSIZE,
52  .DataOUTEndpointDoubleBank = false,
53 
54  .TotalLUNs = TOTAL_LUNS,
55  .PortNumber = 0,
56  },
57 };
58 
59 
60 /*****************************************************************************
61  * Public types/enumerations/variables
62  ****************************************************************************/
63 
64 /*****************************************************************************
65  * Private functions
66  ****************************************************************************/
67 #ifdef OS_FREE_RTOS
68 
69 void usb_msdev_func(void);
70 static xSemaphoreHandle usb_dev_event;
71 
72 /* Task that waits for event from USB device, invokes the USBTask
73  * whenever it receives one
74  */
75 static void usb_msdev_task(void *arg)
76 {
77  vSemaphoreCreateBinary(usb_dev_event);
78  if (usb_dev_event == NULL) {
79  DEBUGSTR("Unable to create semaphore!\r\n");
80  while (1) ;
81  }
82  while (1) {
83  xSemaphoreTake(usb_dev_event, 100);
85  }
86 }
87 
97 void EVENT_USB_Device_TransferComplete(int logicalEP, int xfer_in)
98 {
99  portBASE_TYPE wake = pdFALSE;
100  if (usb_dev_event) {
101  xSemaphoreGiveFromISR(usb_dev_event, &wake);
102  }
103  portEND_SWITCHING_ISR(wake);
104 }
105 
106 /* FreeRTOS USB device task */
107 void usb_device_tasks(void)
108 {
109  /* Start Blinky event Task */
110  xTaskCreate(usb_msdev_task, (signed char *) "USB Task",
112  (xTaskHandle *) NULL);
113 }
114 #elif defined(OS_UCOS_III)
115 
116 #define USBMSDEV_STACK_SZ (1024)
117 #define USBMSDEV_STACK_SZ_FULL 90u
118 #define USBMSDEV_STACK_SZ_LIMIT (USBMSDEV_STACK_SZ * (100u - USBMSDEV_STACK_SZ_FULL)) / 100u
119 
120 void usb_msdev_func(void);
121 static OS_TCB mem_tcb;
123 
124 /* Task that waits for event from USB device, invokes the USBTask
125  * whenever it receives one
126  */
127 static void usb_msdev_task(void *arg)
128 {
129  OS_ERR ucErr;
130  CPU_TS ucos_timeout;
131 
132  while (1) {
133  OSTaskSemPend(100, OS_OPT_PEND_BLOCKING, &ucos_timeout, &ucErr);
134  usb_msdev_func();
135  }
136 }
137 
147 void EVENT_USB_Device_TransferComplete(int logicalEP, int xfer_in)
148 {
149  OS_ERR ucErr;
150  OSTaskSemPost(&mem_tcb, OS_OPT_POST_NONE, &ucErr);
151  if (ucErr != OS_ERR_NONE) {
152  DEBUGSTR("OSTaskSemPost failure!\r\n");
153  //while (1);
154  }
155 
156 }
157 
158 /* uCOS-III USB device task */
159 void usb_device_tasks(void)
160 {
161  OS_ERR ret;
162 
163  /* Start USB event Task */
164  OSTaskCreate (
165  &mem_tcb,
166  "USB Task",
168  (void *) 1,
170  mem_stack,
171  32,
173  0,
174  0,
175  (void *)0,
177  (OS_ERR *)&ret);
178  if (ret != OS_ERR_NONE) {
179  DEBUGSTR("Unable to create USB task!\r\n");
180  while (1);
181  }
182 }
183 
184 #else /* No OS */
185 #define usb_msdev_func usb_device_tasks
186 #endif
187 
188 #ifdef CFG_SDCARD
189 static volatile int32_t sdio_wait_exit = 0;
190 
191 /* Delay callback for timed SDIF/SDMMC functions */
192 static void sdmmc_waitms(uint32_t time)
193 {
194  int32_t curr = (int32_t) Chip_RIT_GetCounter(LPC_RITIMER);
195  int32_t final = curr + ((SystemCoreClock / 1000) * time);
196 
197  /* If the value is zero let us not worry about it */
198  if (!time) {
199  return;
200  }
201 
202  if ((final < 0) && (curr > 0)) {
203  while (Chip_RIT_GetCounter(LPC_RITIMER) < (uint32_t) final) {}
204  }
205  else {
206  while ((int32_t) Chip_RIT_GetCounter(LPC_RITIMER) < final) {}
207  }
208 }
209 
215 static void sdmmc_setup_wakeup(uint32_t bits)
216 {
217  /* Wait for IRQ - for an RTOS, you would pend on an event here with a IRQ based wakeup. */
218  NVIC_ClearPendingIRQ(SDIO_IRQn);
219  sdio_wait_exit = 0;
220  Chip_SDMMC_SetIntMask(LPC_SDMMC, bits);
221  NVIC_EnableIRQ(SDIO_IRQn);
222 }
223 
229 static uint32_t sdmmc_irq_driven_wait(void)
230 {
232 
233  /* Wait for event, would be nice to have a timeout, but keep it simple */
234  while (sdio_wait_exit == 0) {}
235 
236  /* Get status and clear interrupts */
237  status = Chip_SDMMC_GetIntStatus(LPC_SDMMC);
238 
239  return status;
240 }
241 
246 void SDIO_IRQHandler(void)
247 {
248  /* All SD based register handling is done in the callback
249  function. The SDIO interrupt is not enabled as part of this
250  driver and needs to be enabled/disabled in the callbacks or
251  application as needed. This is to allow flexibility with IRQ
252  handling for applicaitons and RTOSes. */
253  /* Set wait exit flag to tell wait function we are ready. In an RTOS,
254  this would trigger wakeup of a thread waiting for the IRQ. */
255  NVIC_DisableIRQ(SDIO_IRQn);
256  sdio_wait_exit = 1;
257 }
258 #endif
259 
260 /*****************************************************************************
261  * Public functions
262  ****************************************************************************/
263 
264 /* USB device initialization */
265 void USBDEV_Init(void)
266 {
267 #ifdef CFG_SDCARD
268  memset(&sdcardinfo, 0, sizeof(sdcardinfo));
269  sdcardinfo.evsetup_cb = sdmmc_setup_wakeup;
270  sdcardinfo.waitfunc_cb = sdmmc_irq_driven_wait;
271  sdcardinfo.msdelay_func = sdmmc_waitms;
272 
273  /* SD/MMC initialization */
275 
276  /* The SDIO driver needs to know the SDIO clock rate */
277  Chip_SDMMC_Init(LPC_SDMMC);
278 
279  /* Wait for a card to be inserted */
280 #ifndef BOARD_NGX_XPLORER_18304330
281  /* NGX board ignored SD_CD pin */
282  /* 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 */
283  while (Chip_SDMMC_CardNDetect(LPC_SDMMC) == 0) {}
284 #endif
285 
286  /* Acquire the card once ready */
288  DEBUGOUT("Card Acquire failed...\r\n");
289  while(1) {};
290  }
291 #endif
292 
293  USB_Init(Disk_MS_Interface.Config.PortNumber, USB_MODE_Device);
294 #if defined(USB_DEVICE_ROM_DRIVER)
295  UsbdMsc_Init();
296 #endif
297  NVIC_SetPriority(USB0_IRQn, IRQ_PRIO_USBDEV);
298 }
299 
300 /* USB Device task */
301 void usb_msdev_func(void)
302 {
303  #if !defined(USB_DEVICE_ROM_DRIVER)
304  MS_Device_USBTask(&Disk_MS_Interface);
305  USB_USBTask(Disk_MS_Interface.Config.PortNumber,USB_MODE_Device);
306  #endif
307 }
310 {}
311 
314 {}
315 
318 {
319  bool ConfigSuccess = true;
320 
321  ConfigSuccess &= MS_Device_ConfigureEndpoints(&Disk_MS_Interface);
322 }
323 
326 {
327  MS_Device_ProcessControlRequest(&Disk_MS_Interface);
328 }
329 
333 {
334  bool CommandSuccess;
335 
336  CommandSuccess = SCSI_DecodeSCSICommand(MSInterfaceInfo);
337  return CommandSuccess;
338 }