2 * This file is part of Cleanflight and Betaflight.
4 * Cleanflight and Betaflight are free software. You can redistribute
5 * this software and/or modify this software under the terms of the
6 * GNU General Public License as published by the Free Software
7 * Foundation, either version 3 of the License, or (at your option)
10 * Cleanflight and Betaflight are distributed in the hope that they
11 * will be useful, but WITHOUT ANY WARRANTY; without even the implied
12 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 * See the GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this software.
18 * If not, see <http://www.gnu.org/licenses/>.
20 * Author: Dominic Clifton
31 #include "drivers/bus_quadspi.h"
32 #include "drivers/bus_quadspi_impl.h"
33 #include "drivers/exti.h"
34 #include "drivers/io.h"
35 #include "drivers/rcc.h"
37 #include "pg/bus_quadspi.h"
39 quadSpiDevice_t quadSpiDevice
[QUADSPIDEV_COUNT
] = { 0 };
41 QUADSPIDevice
quadSpiDeviceByInstance(QUADSPI_TypeDef
*instance
)
43 #ifdef USE_QUADSPI_DEVICE_1
44 if (instance
== QUADSPI
) {
49 return QUADSPIINVALID
;
52 QUADSPI_TypeDef
*quadSpiInstanceByDevice(QUADSPIDevice device
)
54 if (device
== QUADSPIINVALID
|| device
>= QUADSPIDEV_COUNT
) {
58 return quadSpiDevice
[device
].dev
;
61 bool quadSpiInit(QUADSPIDevice device
)
67 #ifdef USE_QUADSPI_DEVICE_1
68 quadSpiInitDevice(device
);
77 uint32_t quadSpiTimeoutUserCallback(QUADSPI_TypeDef
*instance
)
79 QUADSPIDevice device
= quadSpiDeviceByInstance(instance
);
80 if (device
== QUADSPIINVALID
) {
83 quadSpiDevice
[device
].errorCount
++;
84 return quadSpiDevice
[device
].errorCount
;
87 uint16_t quadSpiGetErrorCounter(QUADSPI_TypeDef
*instance
)
89 QUADSPIDevice device
= quadSpiDeviceByInstance(instance
);
90 if (device
== QUADSPIINVALID
) {
93 return quadSpiDevice
[device
].errorCount
;
96 void quadSpiResetErrorCounter(QUADSPI_TypeDef
*instance
)
98 QUADSPIDevice device
= quadSpiDeviceByInstance(instance
);
99 if (device
!= QUADSPIINVALID
) {
100 quadSpiDevice
[device
].errorCount
= 0;
104 const quadSpiHardware_t quadSpiHardware
[] = {
107 .device
= QUADSPIDEV_1
,
110 { DEFIO_TAG_E(PB2
), GPIO_AF9_QUADSPI
},
113 { DEFIO_TAG_E(PC9
), GPIO_AF9_QUADSPI
},
114 { DEFIO_TAG_E(PD11
), GPIO_AF9_QUADSPI
},
115 { DEFIO_TAG_E(PF8
), GPIO_AF10_QUADSPI
},
118 { DEFIO_TAG_E(PC10
), GPIO_AF9_QUADSPI
},
119 { DEFIO_TAG_E(PD12
), GPIO_AF9_QUADSPI
},
120 { DEFIO_TAG_E(PF9
), GPIO_AF10_QUADSPI
},
123 { DEFIO_TAG_E(PE2
), GPIO_AF9_QUADSPI
},
124 { DEFIO_TAG_E(PF7
), GPIO_AF9_QUADSPI
},
127 { DEFIO_TAG_E(PA1
), GPIO_AF9_QUADSPI
},
128 { DEFIO_TAG_E(PD13
), GPIO_AF9_QUADSPI
},
129 { DEFIO_TAG_E(PF6
), GPIO_AF9_QUADSPI
},
132 { DEFIO_TAG_E(PB6
), GPIO_AF10_QUADSPI
},
133 { DEFIO_TAG_E(PB10
), GPIO_AF9_QUADSPI
},
134 { DEFIO_TAG_E(PG6
), GPIO_AF10_QUADSPI
},
137 { DEFIO_TAG_E(PE7
), GPIO_AF10_QUADSPI
},
138 //{ DEFIO_TAG_E(PH7), GPIO_AF9_QUADSPI }, // FIXME regenerate io_def_generated with support for GPIO 'H'
141 { DEFIO_TAG_E(PE8
), GPIO_AF10_QUADSPI
},
142 //{ DEFIO_TAG_E(PH3), GPIO_AF9_QUADSPI }, // FIXME regenerate io_def_generated with support for GPIO 'H'
145 { DEFIO_TAG_E(PE9
), GPIO_AF10_QUADSPI
},
146 { DEFIO_TAG_E(PG9
), GPIO_AF9_QUADSPI
},
149 { DEFIO_TAG_E(PE10
), GPIO_AF10_QUADSPI
},
150 { DEFIO_TAG_E(PG14
), GPIO_AF9_QUADSPI
},
153 { DEFIO_TAG_E(PC11
), GPIO_AF9_QUADSPI
},
155 .rcc
= RCC_AHB3(QSPI
),
160 void quadSpiPinConfigure(const quadSpiConfig_t
*pConfig
)
162 for (size_t hwindex
= 0; hwindex
< ARRAYLEN(quadSpiHardware
); hwindex
++) {
163 const quadSpiHardware_t
*hw
= &quadSpiHardware
[hwindex
];
169 QUADSPIDevice device
= hw
->device
;
170 quadSpiDevice_t
*pDev
= &quadSpiDevice
[device
];
172 for (int pindex
= 0; pindex
< MAX_QUADSPI_PIN_SEL
; pindex
++) {
173 if (pConfig
[device
].ioTagClk
== hw
->clkPins
[pindex
].pin
) {
174 pDev
->clk
= hw
->clkPins
[pindex
].pin
;
179 if (pConfig
[device
].ioTagBK1IO0
== hw
->bk1IO0Pins
[pindex
].pin
) {
180 pDev
->bk1IO0
= hw
->bk1IO0Pins
[pindex
].pin
;
181 pDev
->bk1IO0AF
= hw
->bk1IO0Pins
[pindex
].af
;
183 if (pConfig
[device
].ioTagBK1IO1
== hw
->bk1IO1Pins
[pindex
].pin
) {
184 pDev
->bk1IO1
= hw
->bk1IO1Pins
[pindex
].pin
;
185 pDev
->bk1IO1AF
= hw
->bk1IO1Pins
[pindex
].af
;
187 if (pConfig
[device
].ioTagBK1IO2
== hw
->bk1IO2Pins
[pindex
].pin
) {
188 pDev
->bk1IO2
= hw
->bk1IO2Pins
[pindex
].pin
;
189 pDev
->bk1IO2AF
= hw
->bk1IO2Pins
[pindex
].af
;
191 if (pConfig
[device
].ioTagBK1IO3
== hw
->bk1IO3Pins
[pindex
].pin
) {
192 pDev
->bk1IO3
= hw
->bk1IO3Pins
[pindex
].pin
;
193 pDev
->bk1IO3AF
= hw
->bk1IO3Pins
[pindex
].af
;
195 if (pConfig
[device
].ioTagBK1CS
== hw
->bk1CSPins
[pindex
].pin
) {
196 pDev
->bk1CS
= hw
->bk1CSPins
[pindex
].pin
;
197 pDev
->bk1CSAF
= hw
->bk1CSPins
[pindex
].af
;
202 if (pConfig
[device
].ioTagBK2IO0
== hw
->bk2IO0Pins
[pindex
].pin
) {
203 pDev
->bk2IO0
= hw
->bk2IO0Pins
[pindex
].pin
;
204 pDev
->bk2IO0AF
= hw
->bk2IO0Pins
[pindex
].af
;
206 if (pConfig
[device
].ioTagBK2IO1
== hw
->bk2IO1Pins
[pindex
].pin
) {
207 pDev
->bk2IO1
= hw
->bk2IO1Pins
[pindex
].pin
;
208 pDev
->bk2IO1AF
= hw
->bk2IO1Pins
[pindex
].af
;
210 if (pConfig
[device
].ioTagBK2IO2
== hw
->bk2IO2Pins
[pindex
].pin
) {
211 pDev
->bk2IO2
= hw
->bk2IO2Pins
[pindex
].pin
;
212 pDev
->bk2IO2AF
= hw
->bk2IO2Pins
[pindex
].af
;
214 if (pConfig
[device
].ioTagBK2IO3
== hw
->bk2IO3Pins
[pindex
].pin
) {
215 pDev
->bk2IO3
= hw
->bk2IO3Pins
[pindex
].pin
;
216 pDev
->bk2IO3AF
= hw
->bk2IO3Pins
[pindex
].af
;
218 if (pConfig
[device
].ioTagBK2CS
== hw
->bk2CSPins
[pindex
].pin
) {
219 pDev
->bk2CS
= hw
->bk2CSPins
[pindex
].pin
;
220 pDev
->bk2CSAF
= hw
->bk2CSPins
[pindex
].af
;
224 if ((quadSpiConfig(device
)->csFlags
& QUADSPI_BK1_CS_MASK
) == QUADSPI_BK1_CS_SOFTWARE
) {
225 pDev
->bk1CS
= pConfig
[device
].ioTagBK1CS
;
227 if ((quadSpiConfig(device
)->csFlags
& QUADSPI_BK2_CS_MASK
) == QUADSPI_BK2_CS_SOFTWARE
) {
228 pDev
->bk2CS
= pConfig
[device
].ioTagBK2CS
;
231 bool haveResources
= true;
235 haveResources
= haveResources
&& pDev
->clk
;
239 bool needBK1
= (pConfig
[device
].mode
== QUADSPI_MODE_DUAL_FLASH
) || (pConfig
[device
].mode
== QUADSPI_MODE_BK1_ONLY
);
241 bool haveBK1Resources
= pDev
->bk1IO0
&& pDev
->bk1IO1
&& pDev
->bk1IO2
&& pDev
->bk1IO3
&& pDev
->bk1CS
;
242 haveResources
= haveResources
&& haveBK1Resources
;
245 bool needBK2
= (pConfig
[device
].mode
== QUADSPI_MODE_DUAL_FLASH
) || (pConfig
[device
].mode
== QUADSPI_MODE_BK2_ONLY
);
247 bool haveBK2Resources
= pDev
->bk2IO0
&& pDev
->bk2IO1
&& pDev
->bk2IO2
&& pDev
->bk2IO3
;
248 haveResources
= haveResources
&& haveBK2Resources
;
254 haveResources
= haveResources
&& pDev
->bk1CS
;
258 (pConfig
[device
].mode
== QUADSPI_MODE_DUAL_FLASH
&& (pConfig
[device
].csFlags
& QUADSPI_CS_MODE_MASK
) == QUADSPI_CS_MODE_SEPARATE
) ||
259 (pConfig
[device
].mode
== QUADSPI_MODE_BK2_ONLY
);
262 haveResources
= haveResources
&& pDev
->bk2CS
;