Add SD keep-alive to ensure it responds immediately
[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 #ifdef STM32F2xx\r
19 #include "stm32f2xx.h"\r
20 #endif\r
21 \r
22 #ifdef STM32F4xx\r
23 #include "stm32f4xx.h"\r
24 #endif\r
25 \r
26 \r
27 #include "config.h"\r
28 #include "disk.h"\r
29 #include "fpga.h"\r
30 #include "hwversion.h"\r
31 #include "led.h"\r
32 #include "sd.h"\r
33 #include "scsi.h"\r
34 #include "scsiPhy.h"\r
35 #include "time.h"\r
36 #include "sdio.h"\r
37 #include "usb_device/usb_device.h"\r
38 #include "usb_device/usbd_composite.h"\r
39 #include "usb_device/usbd_msc_storage_sd.h"\r
40 \r
41 #include "bsp_driver_sd.h"\r
42 \r
43 const char* Notice = "Copyright (C) 2020 Michael McMaster <michael@codesrc.com>";\r
44 uint32_t lastSDPoll;\r
45 uint32_t lastSDKeepAlive;\r
46 \r
47 static int isUsbStarted;\r
48 \r
49 // Note that the chip clocking isn't fully configured at this stage.\r
50 void mainEarlyInit()\r
51 {\r
52 #ifdef nULPI_RESET_GPIO_Port\r
53     // Disable the ULPI chip\r
54     HAL_GPIO_WritePin(nULPI_RESET_GPIO_Port, nULPI_RESET_Pin, GPIO_PIN_RESET);\r
55 #endif\r
56 \r
57     // Sets up function pointers only\r
58     s2s_initUsbDeviceStorage();\r
59 }\r
60 \r
61 void mainInit()\r
62 {\r
63     s2s_timeInit();\r
64     s2s_checkHwVersion();\r
65 \r
66     s2s_ledInit();\r
67     s2s_fpgaInit();\r
68 \r
69     scsiPhyInit();\r
70 \r
71     scsiDiskInit();\r
72     sdInit();\r
73     s2s_configInit(&scsiDev.boardCfg);\r
74     scsiPhyConfig();\r
75     scsiInit();\r
76 \r
77     #ifdef S2S_USB_HS\r
78         // Enable the ULPI chip\r
79         HAL_GPIO_WritePin(nULPI_RESET_GPIO_Port, nULPI_RESET_Pin, GPIO_PIN_SET);\r
80         s2s_delay_ms(5);\r
81     #endif\r
82 \r
83     MX_USB_DEVICE_Init(); // USB lun config now available.\r
84     isUsbStarted = 1;\r
85 \r
86     // Optional bootup delay\r
87     int delaySeconds = 0;\r
88     while (delaySeconds < scsiDev.boardCfg.startupDelay) {\r
89         // Keep the USB connection working, otherwise it's very hard to revert\r
90         // silly extra-long startup delay settings.\r
91         int i;\r
92         for (i = 0; i < 200; i++) {\r
93             s2s_delay_ms(5);\r
94             scsiDev.watchdogTick++;\r
95             s2s_configPoll();\r
96         }\r
97         ++delaySeconds;\r
98     }\r
99 \r
100 #ifdef TEST_SD_CARDS\r
101     s2s_ledOn();\r
102     for (int h = 0; h < 1000; ++h)\r
103     {\r
104         uint8_t g = BSP_SD_ReadBlocks_DMA(scsiDev.data, (1000 - h) * 1000, 64);\r
105         if (g != MSD_OK)\r
106         {\r
107             while (1) {}\r
108         }\r
109         if (h & 1)\r
110         {\r
111             uint8_t r = BSP_SD_ReadBlocks_DMA(scsiDev.data, h * 1000, 1);\r
112             if (r != MSD_OK)\r
113             {\r
114                 while (1) {}\r
115             }\r
116         }\r
117         else\r
118         {\r
119             uint8_t random[1024];\r
120             for (int p = 0; p < 512; ++p) random[p] = h + p ^ 0xAA;\r
121             BSP_SD_WriteBlocks_DMA(random, h * 2000, 1);\r
122             BSP_SD_ReadBlocks_DMA(scsiDev.data, h * 2000, 1);\r
123             BSP_SD_WriteBlocks_DMA(random, h * 2000 + 1, 2);\r
124             BSP_SD_ReadBlocks_DMA(&(scsiDev.data[512]), h * 2000 + 1, 2);\r
125             if (memcmp(random, scsiDev.data, 512) ||\r
126                 memcmp(random, &(scsiDev.data[512]), 1024))\r
127             {\r
128                 while (1) {}\r
129             }\r
130         }\r
131     }\r
132     s2s_ledOff();\r
133 #endif\r
134 \r
135     lastSDPoll = lastSDKeepAlive = s2s_getTime_ms();\r
136 }\r
137 \r
138 void mainLoop()\r
139 {\r
140     scsiDev.watchdogTick++;\r
141 \r
142     scsiPoll();\r
143     scsiDiskPoll();\r
144     s2s_configPoll();\r
145 \r
146 #ifdef S2S_USB_FS\r
147     int usbBusy = s2s_usbDevicePoll(&hUsbDeviceFS);\r
148 #endif\r
149 #ifdef S2S_USB_HS\r
150     int usbBusy = s2s_usbDevicePoll(&hUsbDeviceHS);\r
151 #endif\r
152 \r
153 #if 0\r
154     sdPoll();\r
155 #endif\r
156 \r
157     // TODO test if USB transfer is in progress\r
158     if (unlikely(scsiDev.phase == BUS_FREE) && !usbBusy)\r
159     {\r
160         if (unlikely(s2s_elapsedTime_ms(lastSDPoll) > 200))\r
161         {\r
162             lastSDPoll = s2s_getTime_ms();\r
163             if (sdInit())\r
164             {\r
165                 s2s_configInit(&scsiDev.boardCfg);\r
166                 scsiPhyConfig();\r
167                 scsiInit();\r
168 \r
169                 if (isUsbStarted)\r
170                 {\r
171 #ifdef S2S_USB_FS\r
172                     USBD_Stop(&hUsbDeviceFS);\r
173                     s2s_delay_ms(128);\r
174                     USBD_Start(&hUsbDeviceFS);\r
175 #endif\r
176 #ifdef S2S_USB_HS\r
177                     USBD_Stop(&hUsbDeviceHS);\r
178                     s2s_delay_ms(128);\r
179                     USBD_Start(&hUsbDeviceHS);\r
180 #endif\r
181                 }\r
182             }\r
183         }\r
184         else if (lastSDKeepAlive > 10000) // 10 seconds\r
185         {\r
186             // 2021 boards fail if there's no commands sent in a while\r
187             sdKeepAlive();\r
188             lastSDKeepAlive = s2s_getTime_ms();\r
189         }\r
190     }\r
191     else if (usbBusy || ((scsiDev.phase >= 0) && (blockDev.state & DISK_PRESENT)))\r
192     {\r
193         // don't waste time scanning SD cards while we're doing disk IO\r
194         lastSDPoll = lastSDKeepAlive = s2s_getTime_ms();\r
195     }\r
196 }\r
197 \r