00001 00038 #include <led.h> 00039 #include <gpio.h> 00040 #include <board.h> 00041 #include <debug.h> 00042 #include <dmapool.h> 00043 #include <mainloop.h> 00044 #include <clk/sys.h> 00045 #include <usb/dev_mux.h> 00046 #include <usb/request.h> 00047 #include <usb/udc.h> 00048 00049 #include "xplain-bc.h" 00050 00051 static struct app_usb_mode_task *app_usb_mode_task_of_task( 00052 struct workqueue_task *task) 00053 { 00054 return container_of(task, struct app_usb_mode_task, task); 00055 } 00056 00073 static void app_usb_mode_worker(struct workqueue_task *task) 00074 { 00075 struct app_usb_mode_task *usb_mode_task; 00076 bool is_usb_msc_mode; 00077 00078 usb_mode_task = app_usb_mode_task_of_task(task); 00079 is_usb_msc_mode = board_gpio_is_usb_msc_mode(); 00080 00081 /* Check if MSC is enabled and mode pin is high (i.e. disable it). */ 00082 if (usb_mode_task->msc_enabled && !is_usb_msc_mode) { 00083 /* 00084 * If SPI is busy, wait for it to complete. \todo Correct usage 00085 * master.base.status check for OPERATION_IN_PROGRESS? 00086 */ 00087 if (usb_mode_task->master.base.status == OPERATION_IN_PROGRESS) 00088 goto out_retry; 00089 00090 /* Detach to the USB bus, disabling the MSC interface. */ 00091 udc_detach(usb_mode_task->udc); 00092 usb_mode_task->msc_enabled = false; 00093 00094 /* Set the SPI in slave mode. */ 00095 board_gpio_set_spi_master_mode(false); 00096 00097 /* Release the XMEGA chip from reset, SPI bus is now ready. */ 00098 board_gpio_mcu_reset(false); 00099 led_deactivate(BOARD_LED_RED); 00100 } 00101 /* Check if MSC is disabled and mode pin is low (i.e. enable it). */ 00102 else if (!usb_mode_task->msc_enabled && is_usb_msc_mode) { 00103 /* The XMEGA interferes on the SPI bus, keep it in reset. */ 00104 board_gpio_mcu_reset(true); 00105 00106 /* Set the SPI in master mode. */ 00107 board_gpio_set_spi_master_mode(true); 00108 00109 /* Attach to the USB bus, disabling the MSC interface. */ 00110 udc_attach(usb_mode_task->udc); 00111 usb_mode_task->msc_enabled = true; 00112 led_activate(BOARD_LED_RED); 00113 } 00114 00119 out_retry: 00120 workqueue_add_task(&main_workqueue, &usb_mode_task->task); 00121 } 00122 00130 static void app_dataflash_ready(struct workqueue_task *task) 00131 { 00132 struct app_usb_mode_task *usb_mode_task; 00133 usb_mode_task = app_usb_mode_task_of_task(task); 00134 board_gpio_set_spi_master_mode(false); 00135 board_gpio_mcu_reset(false); 00136 workqueue_task_set_work_func(&usb_mode_task->task, app_usb_mode_worker); 00137 workqueue_add_task(&main_workqueue, &usb_mode_task->task); 00138 } 00139 00148 int main(void) 00149 { 00150 static struct app_usb_mode_task usb_mode_task; 00151 struct udc *udc; 00152 00153 cpu_irq_enable(); 00154 sysclk_init(); 00155 dbg_init(); 00156 board_init(); 00157 workqueue_init(&main_workqueue); 00158 dma_pool_init(); 00159 buffer_pool_init(); 00160 usb_init(); 00161 00162 dbg_info("USB Mass Storage device initializing...\n"); 00163 00164 udc = udc_init(); 00165 if (!udc) { 00166 dbg_panic("UDC initialization failed\n"); 00167 return 1; 00168 } 00169 00170 usb_mode_task.udc = udc; 00171 usb_mode_task.msc_enabled = false; 00172 00173 workqueue_task_init(&(usb_mode_task.task), app_usb_mode_worker); 00174 00175 /* Check USB mode pin to see if USB should be attached or detached at 00176 * startup. If MSC interface should not be enabled set workqueue to 00177 * app_dataflash_ready, which will set the SPI interface in slave mode 00178 * and release the XMEGA reset line. 00179 */ 00180 if (!board_gpio_is_usb_msc_mode()) { 00181 workqueue_task_set_work_func(&usb_mode_task.task, 00182 app_dataflash_ready); 00183 } 00184 00185 dataflash_init(&usb_mode_task); 00186 mainloop_run(&main_workqueue); 00187 }
1.6.3