Fix terrible performance
[SCSI2SD-V6.git] / src / firmware / main.c
1 //      Copyright (C) 2014 Michael McMaster <michael@codesrc.com>\r
2 //\r
3 //      This file is part of SCSI2SD.\r
4 //\r
5 //      SCSI2SD is free software: you can redistribute it and/or modify\r
6 //      it under the terms of the GNU General Public License as published by\r
7 //      the Free Software Foundation, either version 3 of the License, or\r
8 //      (at your option) any later version.\r
9 //\r
10 //      SCSI2SD is distributed in the hope that it will be useful,\r
11 //      but WITHOUT ANY WARRANTY; without even the implied warranty of\r
12 //      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
13 //      GNU General Public License for more details.\r
14 //\r
15 //      You should have received a copy of the GNU General Public License\r
16 //      along with SCSI2SD.  If not, see <http://www.gnu.org/licenses/>.\r
17 \r
18 #include "stm32f2xx.h"\r
19 \r
20 #include "config.h"\r
21 #include "disk.h"\r
22 #include "fpga.h"\r
23 #include "led.h"\r
24 #include "sd.h"\r
25 #include "scsi.h"\r
26 #include "scsiPhy.h"\r
27 #include "time.h"\r
28 #include "trace.h"\r
29 #include "usb_device/usb_device.h"\r
30 #include "usb_device/usbd_composite.h"\r
31 #include "usb_device/usbd_msc_storage_sd.h"\r
32 \r
33 \r
34 const char* Notice = "Copyright (C) 2016 Michael McMaster <michael@codesrc.com>";\r
35 uint32_t lastSDPoll;\r
36 \r
37 void mainEarlyInit()\r
38 {\r
39         // USB device is initialised before mainInit is called\r
40         s2s_initUsbDeviceStorage();\r
41 }\r
42 \r
43 void mainInit()\r
44 {\r
45         traceInit();\r
46         s2s_timeInit();\r
47         s2s_ledInit();\r
48         s2s_fpgaInit();\r
49 \r
50         scsiPhyInit();\r
51 \r
52         scsiDiskInit();\r
53         sdInit();\r
54         s2s_configInit(&scsiDev.boardCfg);\r
55         scsiPhyConfig();\r
56         scsiInit();\r
57 \r
58         MX_USB_DEVICE_Init(); // USB lun config now available.\r
59 \r
60         // Optional bootup delay\r
61         int delaySeconds = 0;\r
62         while (delaySeconds < scsiDev.boardCfg.startupDelay) {\r
63                 // Keep the USB connection working, otherwise it's very hard to revert\r
64                 // silly extra-long startup delay settings.\r
65                 int i;\r
66                 for (i = 0; i < 200; i++) {\r
67                         s2s_delay_ms(5);\r
68                         scsiDev.watchdogTick++;\r
69                         s2s_configPoll();\r
70                 }\r
71                 ++delaySeconds;\r
72         }\r
73 \r
74         lastSDPoll = s2s_getTime_ms();\r
75 }\r
76 \r
77 void mainLoop()\r
78 {\r
79         scsiDev.watchdogTick++;\r
80 \r
81         scsiPoll();\r
82         scsiDiskPoll();\r
83         s2s_configPoll();\r
84         s2s_usbDevicePoll();\r
85 \r
86 #if 0\r
87         sdPoll();\r
88 #endif\r
89 \r
90         if (unlikely(scsiDev.phase == BUS_FREE))\r
91         {\r
92                 if (unlikely(s2s_elapsedTime_ms(lastSDPoll) > 200))\r
93                 {\r
94                         lastSDPoll = s2s_getTime_ms();\r
95                         if (sdInit())\r
96                         {\r
97                                 s2s_configInit(&scsiDev.boardCfg);\r
98                                 scsiPhyConfig();\r
99                                 scsiInit();\r
100 \r
101 \r
102                                 USBD_Stop(&hUsbDeviceFS);\r
103                                 s2s_delay_ms(128);\r
104                                 USBD_Start(&hUsbDeviceFS);\r
105                         }\r
106                 }\r
107                 else\r
108                 {\r
109                         // TODO this hurts performance significantly! Work out why __WFI()\r
110                         // doesn't wake up immediately !\r
111 #if 0\r
112                         // Wait for our 1ms timer to save some power.\r
113                         // There's an interrupt on the SEL signal to ensure we respond\r
114                         // quickly to any SCSI commands. The selection abort time is\r
115                         // only 250us, and new SCSI-3 controllers time-out very\r
116                         // not long after that, so we need to ensure we wake up quickly.\r
117                         uint32_t interruptState = __get_PRIMASK();\r
118                         __disable_irq();\r
119 \r
120                         if (!*SCSI_STS_SELECTED)\r
121                         {\r
122                                 //__WFI(); // Will wake on interrupt, regardless of mask\r
123                         }\r
124                         if (!interruptState)\r
125                         {\r
126                                 __enable_irq();\r
127                         }\r
128 #endif\r
129                 }\r
130         }\r
131         else if (scsiDev.phase >= 0)\r
132         {\r
133                 // don't waste time scanning SD cards while we're doing disk IO\r
134                 lastSDPoll = s2s_getTime_ms();\r
135         }\r
136 }\r
137 \r