Blackbox device type 'file' (SITL) considered working when file handler is available
[inav.git] / src / main / drivers / bus_quadspi_hal.c
blob0d5215ab2fc0e7b114aa311fd7da4fd42e03a51b
1 /*
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)
8 * any later version.
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
23 #include <stdbool.h>
24 #include <stdint.h>
26 #include "platform.h"
28 #ifdef USE_QUADSPI
30 #include "bus_quadspi.h"
31 #include "bus_quadspi_impl.h"
32 #include "dma.h"
33 #include "io.h"
34 #include "io_impl.h"
35 #include "nvic.h"
36 #include "rcc.h"
38 static void Error_Handler(void) { while (1) { } }
40 void quadSpiInitDevice(QUADSPIDevice device)
42 quadSpiDevice_t *quadSpi = &(quadSpiDevice[device]);
44 // Enable QUADSPI clock
45 RCC_ClockCmd(quadSpi->rcc, ENABLE);
46 //RCC_ResetCmd(quadSpi->rcc, ENABLE);
48 IOInit(IOGetByTag(quadSpi->clk), OWNER_QUADSPI, RESOURCE_QUADSPI_CLK, RESOURCE_INDEX(device));
49 IOInit(IOGetByTag(quadSpi->bk1IO0), OWNER_QUADSPI, RESOURCE_QUADSPI_BK1IO0, RESOURCE_INDEX(device));
50 IOInit(IOGetByTag(quadSpi->bk1IO1), OWNER_QUADSPI, RESOURCE_QUADSPI_BK1IO1, RESOURCE_INDEX(device));
51 IOInit(IOGetByTag(quadSpi->bk1IO2), OWNER_QUADSPI, RESOURCE_QUADSPI_BK1IO2, RESOURCE_INDEX(device));
52 IOInit(IOGetByTag(quadSpi->bk1IO3), OWNER_QUADSPI, RESOURCE_QUADSPI_BK1IO3, RESOURCE_INDEX(device));
53 IOInit(IOGetByTag(quadSpi->bk1CS), OWNER_QUADSPI, RESOURCE_QUADSPI_BK1CS, RESOURCE_INDEX(device));
55 IOInit(IOGetByTag(quadSpi->bk2IO0), OWNER_QUADSPI, RESOURCE_QUADSPI_BK2IO0, RESOURCE_INDEX(device));
56 IOInit(IOGetByTag(quadSpi->bk2IO1), OWNER_QUADSPI, RESOURCE_QUADSPI_BK2IO1, RESOURCE_INDEX(device));
57 IOInit(IOGetByTag(quadSpi->bk2IO2), OWNER_QUADSPI, RESOURCE_QUADSPI_BK2IO2, RESOURCE_INDEX(device));
58 IOInit(IOGetByTag(quadSpi->bk2IO3), OWNER_QUADSPI, RESOURCE_QUADSPI_BK2IO3, RESOURCE_INDEX(device));
59 IOInit(IOGetByTag(quadSpi->bk2CS), OWNER_QUADSPI, RESOURCE_QUADSPI_BK2CS, RESOURCE_INDEX(device));
61 #if defined(STM32H7)
62 // clock is only on AF9
63 // IO and CS lines are on AF9 and AF10
64 IOConfigGPIOAF(IOGetByTag(quadSpi->clk), QUADSPI_IO_AF_CLK_CFG, GPIO_AF9_QUADSPI);
65 IOConfigGPIOAF(IOGetByTag(quadSpi->bk1IO0), QUADSPI_IO_AF_BK_IO_CFG, quadSpi->bk1IO0AF);
66 IOConfigGPIOAF(IOGetByTag(quadSpi->bk1IO1), QUADSPI_IO_AF_BK_IO_CFG, quadSpi->bk1IO1AF);
67 IOConfigGPIOAF(IOGetByTag(quadSpi->bk1IO2), QUADSPI_IO_AF_BK_IO_CFG, quadSpi->bk1IO2AF);
68 IOConfigGPIOAF(IOGetByTag(quadSpi->bk1IO3), QUADSPI_IO_AF_BK_IO_CFG, quadSpi->bk1IO3AF);
69 IOConfigGPIOAF(IOGetByTag(quadSpi->bk2IO0), QUADSPI_IO_AF_BK_IO_CFG, quadSpi->bk2IO0AF);
70 IOConfigGPIOAF(IOGetByTag(quadSpi->bk2IO1), QUADSPI_IO_AF_BK_IO_CFG, quadSpi->bk2IO1AF);
71 IOConfigGPIOAF(IOGetByTag(quadSpi->bk2IO2), QUADSPI_IO_AF_BK_IO_CFG, quadSpi->bk2IO2AF);
72 IOConfigGPIOAF(IOGetByTag(quadSpi->bk2IO3), QUADSPI_IO_AF_BK_IO_CFG, quadSpi->bk2IO3AF);
74 if ((quadSpi->csFlags & QUADSPI_BK1_CS_MASK) == QUADSPI_BK1_CS_HARDWARE) {
75 IOConfigGPIOAF(IOGetByTag(quadSpi->bk1CS), QUADSPI_IO_AF_BK_CS_CFG, quadSpi->bk1CSAF);
76 } else {
77 IOConfigGPIO(IOGetByTag(quadSpi->bk1CS), QUADSPI_IO_BK_CS_CFG);
80 if ((quadSpi->csFlags & QUADSPI_BK2_CS_MASK) == QUADSPI_BK2_CS_HARDWARE) {
81 IOConfigGPIOAF(IOGetByTag(quadSpi->bk2CS), QUADSPI_IO_AF_BK_CS_CFG, quadSpi->bk2CSAF);
82 } else {
83 IOConfigGPIO(IOGetByTag(quadSpi->bk2CS), QUADSPI_IO_BK_CS_CFG);
85 #endif
87 quadSpi->hquadSpi.Instance = quadSpi->dev;
88 // DeInit QUADSPI hardware
89 HAL_QSPI_DeInit(&quadSpi->hquadSpi);
91 quadSpi->hquadSpi.Init.ClockPrescaler = QUADSPI_CLOCK_INITIALISATION;
92 quadSpi->hquadSpi.Init.FifoThreshold = 1;
93 quadSpi->hquadSpi.Init.SampleShifting = QSPI_SAMPLE_SHIFTING_NONE;
94 quadSpi->hquadSpi.Init.FlashSize = 23; // address bits + 1
95 quadSpi->hquadSpi.Init.ChipSelectHighTime = QSPI_CS_HIGH_TIME_1_CYCLE;
96 quadSpi->hquadSpi.Init.ClockMode = QSPI_CLOCK_MODE_0;
98 switch (quadSpi->mode) {
99 case QUADSPI_MODE_BK1_ONLY:
100 quadSpi->hquadSpi.Init.FlashID = QSPI_FLASH_ID_1;
101 quadSpi->hquadSpi.Init.DualFlash = QSPI_DUALFLASH_DISABLE;
102 break;
103 case QUADSPI_MODE_BK2_ONLY:
104 quadSpi->hquadSpi.Init.FlashID = QSPI_FLASH_ID_2;
105 quadSpi->hquadSpi.Init.DualFlash = QSPI_DUALFLASH_DISABLE;
106 break;
107 case QUADSPI_MODE_DUAL_FLASH:
108 quadSpi->hquadSpi.Init.DualFlash = QSPI_DUALFLASH_ENABLE;
109 break;
112 // Init QUADSPI hardware
113 if (HAL_QSPI_Init(&quadSpi->hquadSpi) != HAL_OK)
115 Error_Handler();
119 static const uint32_t quadSpi_addressSizeMap[] = {
120 QSPI_ADDRESS_8_BITS,
121 QSPI_ADDRESS_16_BITS,
122 QSPI_ADDRESS_24_BITS,
123 QSPI_ADDRESS_32_BITS
126 static uint32_t quadSpi_addressSizeFromValue(uint8_t addressSize)
128 return quadSpi_addressSizeMap[((addressSize + 1) / 8) - 1]; // rounds to nearest QSPI_ADDRESS_* value that will hold the address.
132 * Return true if the bus is currently in the middle of a transmission.
134 bool quadSpiIsBusBusy(QUADSPI_TypeDef *instance)
136 QUADSPIDevice device = quadSpiDeviceByInstance(instance);
137 if(quadSpiDevice[device].hquadSpi.State == HAL_QSPI_STATE_BUSY)
138 return true;
139 else
140 return false;
143 #define QUADSPI_DEFAULT_TIMEOUT 10
145 void quadSpiSelectDevice(QUADSPI_TypeDef *instance)
147 QUADSPIDevice device = quadSpiDeviceByInstance(instance);
149 quadSpiDevice_t *quadSpi = &(quadSpiDevice[device]);
151 IO_t bk1CS = IOGetByTag(quadSpi->bk1CS);
152 IO_t bk2CS = IOGetByTag(quadSpi->bk2CS);
154 switch(quadSpi->mode) {
155 case QUADSPI_MODE_DUAL_FLASH:
156 if ((quadSpi->csFlags & QUADSPI_BK1_CS_MASK) == QUADSPI_BK1_CS_SOFTWARE) {
157 IOLo(bk1CS);
159 if ((quadSpi->csFlags & QUADSPI_BK2_CS_MASK) == QUADSPI_BK2_CS_SOFTWARE) {
160 IOLo(bk2CS);
162 break;
163 case QUADSPI_MODE_BK1_ONLY:
164 if ((quadSpi->csFlags & QUADSPI_BK1_CS_MASK) == QUADSPI_BK1_CS_SOFTWARE) {
165 IOLo(bk1CS);
167 break;
168 case QUADSPI_MODE_BK2_ONLY:
169 if ((quadSpi->csFlags & QUADSPI_BK2_CS_MASK) == QUADSPI_BK2_CS_SOFTWARE) {
170 IOLo(bk2CS);
172 break;
176 void quadSpiDeselectDevice(QUADSPI_TypeDef *instance)
178 QUADSPIDevice device = quadSpiDeviceByInstance(instance);
180 quadSpiDevice_t *quadSpi = &(quadSpiDevice[device]);
182 IO_t bk1CS = IOGetByTag(quadSpi->bk1CS);
183 IO_t bk2CS = IOGetByTag(quadSpi->bk2CS);
185 switch(quadSpi->mode) {
186 case QUADSPI_MODE_DUAL_FLASH:
187 if ((quadSpi->csFlags & QUADSPI_BK1_CS_MASK) == QUADSPI_BK1_CS_SOFTWARE) {
188 IOHi(bk1CS);
190 if ((quadSpi->csFlags & QUADSPI_BK2_CS_MASK) == QUADSPI_BK2_CS_SOFTWARE) {
191 IOHi(bk2CS);
193 break;
194 case QUADSPI_MODE_BK1_ONLY:
195 if ((quadSpi->csFlags & QUADSPI_BK1_CS_MASK) == QUADSPI_BK1_CS_SOFTWARE) {
196 IOHi(bk1CS);
198 break;
199 case QUADSPI_MODE_BK2_ONLY:
200 if ((quadSpi->csFlags & QUADSPI_BK2_CS_MASK) == QUADSPI_BK2_CS_SOFTWARE) {
201 IOHi(bk2CS);
203 break;
209 bool quadSpiTransmit1LINE(QUADSPI_TypeDef *instance, uint8_t instruction, uint8_t dummyCycles, const uint8_t *out, int length)
211 QUADSPIDevice device = quadSpiDeviceByInstance(instance);
212 HAL_StatusTypeDef status;
215 QSPI_CommandTypeDef cmd;
216 cmd.InstructionMode = QSPI_INSTRUCTION_1_LINE;
217 cmd.AddressMode = QSPI_ADDRESS_NONE;
218 cmd.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
219 cmd.DataMode = QSPI_DATA_NONE;
220 cmd.DummyCycles = dummyCycles;
221 cmd.DdrMode = QSPI_DDR_MODE_DISABLE;
222 cmd.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;
223 cmd.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;
225 cmd.Instruction = instruction;
226 cmd.NbData = length;
228 if (out) {
229 cmd.DataMode = QSPI_DATA_1_LINE;
232 quadSpiSelectDevice(instance);
234 status = HAL_QSPI_Command(&quadSpiDevice[device].hquadSpi, &cmd, QUADSPI_DEFAULT_TIMEOUT);
235 bool timeout = (status != HAL_OK);
236 if (!timeout) {
237 if (out && length > 0) {
238 status = HAL_QSPI_Transmit(&quadSpiDevice[device].hquadSpi, (uint8_t *)out, QUADSPI_DEFAULT_TIMEOUT);
239 timeout = (status != HAL_OK);
243 quadSpiDeselectDevice(instance);
245 if (timeout) {
246 quadSpiTimeoutUserCallback(instance);
247 return false;
250 return true;
253 bool quadSpiReceive1LINE(QUADSPI_TypeDef *instance, uint8_t instruction, uint8_t dummyCycles, uint8_t *in, int length)
255 QUADSPIDevice device = quadSpiDeviceByInstance(instance);
256 HAL_StatusTypeDef status;
258 QSPI_CommandTypeDef cmd;
259 cmd.InstructionMode = QSPI_INSTRUCTION_1_LINE;
260 cmd.AddressMode = QSPI_ADDRESS_NONE;
261 cmd.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
262 cmd.DataMode = QSPI_DATA_1_LINE;
263 cmd.DummyCycles = dummyCycles;
264 cmd.DdrMode = QSPI_DDR_MODE_DISABLE;
265 cmd.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;
266 cmd.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;
268 cmd.Instruction = instruction;
269 cmd.NbData = length;
271 quadSpiSelectDevice(instance);
273 status = HAL_QSPI_Command(&quadSpiDevice[device].hquadSpi, &cmd, QUADSPI_DEFAULT_TIMEOUT);
274 bool timeout = (status != HAL_OK);
275 if (!timeout) {
276 status = HAL_QSPI_Receive(&quadSpiDevice[device].hquadSpi, in, QUADSPI_DEFAULT_TIMEOUT);
278 timeout = (status != HAL_OK);
281 quadSpiDeselectDevice(instance);
283 if (timeout) {
284 quadSpiTimeoutUserCallback(instance);
285 return false;
288 return true;
291 bool quadSpiReceive4LINES(QUADSPI_TypeDef *instance, uint8_t instruction, uint8_t dummyCycles, uint8_t *in, int length)
293 QUADSPIDevice device = quadSpiDeviceByInstance(instance);
294 HAL_StatusTypeDef status;
296 QSPI_CommandTypeDef cmd;
297 cmd.InstructionMode = QSPI_INSTRUCTION_4_LINES;
298 cmd.AddressMode = QSPI_ADDRESS_NONE;
299 cmd.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
300 cmd.DataMode = QSPI_DATA_4_LINES;
301 cmd.DummyCycles = dummyCycles;
302 cmd.DdrMode = QSPI_DDR_MODE_DISABLE;
303 cmd.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;
304 cmd.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;
306 cmd.Instruction = instruction;
307 cmd.NbData = length;
309 quadSpiSelectDevice(instance);
311 status = HAL_QSPI_Command(&quadSpiDevice[device].hquadSpi, &cmd, QUADSPI_DEFAULT_TIMEOUT);
312 bool timeout = (status != HAL_OK);
313 if (!timeout) {
314 status = HAL_QSPI_Receive(&quadSpiDevice[device].hquadSpi, in, QUADSPI_DEFAULT_TIMEOUT);
316 timeout = (status != HAL_OK);
319 quadSpiDeselectDevice(instance);
321 if (timeout) {
322 quadSpiTimeoutUserCallback(instance);
323 return false;
326 return true;
329 bool quadSpiReceiveWithAddress1LINE(QUADSPI_TypeDef *instance, uint8_t instruction, uint8_t dummyCycles, uint32_t address, uint8_t addressSize, uint8_t *in, int length)
331 QUADSPIDevice device = quadSpiDeviceByInstance(instance);
332 HAL_StatusTypeDef status;
334 QSPI_CommandTypeDef cmd;
335 cmd.InstructionMode = QSPI_INSTRUCTION_1_LINE;
336 cmd.AddressMode = QSPI_ADDRESS_1_LINE;
337 cmd.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
338 cmd.DataMode = QSPI_DATA_1_LINE;
339 cmd.DummyCycles = dummyCycles;
340 cmd.DdrMode = QSPI_DDR_MODE_DISABLE;
341 cmd.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;
342 cmd.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;
344 cmd.Instruction = instruction;
345 cmd.Address = address;
346 cmd.AddressSize = quadSpi_addressSizeFromValue(addressSize);
347 cmd.NbData = length;
349 quadSpiSelectDevice(instance);
351 status = HAL_QSPI_Command(&quadSpiDevice[device].hquadSpi, &cmd, QUADSPI_DEFAULT_TIMEOUT);
352 bool timeout = (status != HAL_OK);
353 if (!timeout) {
354 status = HAL_QSPI_Receive(&quadSpiDevice[device].hquadSpi, in, QUADSPI_DEFAULT_TIMEOUT);
355 timeout = (status != HAL_OK);
358 quadSpiDeselectDevice(instance);
360 if (timeout) {
361 quadSpiTimeoutUserCallback(instance);
362 return false;
365 return true;
369 bool quadSpiReceiveWithAddress4LINES(QUADSPI_TypeDef *instance, uint8_t instruction, uint8_t dummyCycles, uint32_t address, uint8_t addressSize, uint8_t *in, int length)
371 QUADSPIDevice device = quadSpiDeviceByInstance(instance);
372 HAL_StatusTypeDef status;
374 QSPI_CommandTypeDef cmd;
375 cmd.InstructionMode = QSPI_INSTRUCTION_1_LINE;
376 cmd.AddressMode = QSPI_ADDRESS_1_LINE;
377 cmd.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
378 cmd.DataMode = QSPI_DATA_4_LINES;
379 cmd.DummyCycles = dummyCycles;
380 cmd.DdrMode = QSPI_DDR_MODE_DISABLE;
381 cmd.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;
382 cmd.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;
384 cmd.Instruction = instruction;
385 cmd.Address = address;
386 cmd.AddressSize = quadSpi_addressSizeFromValue(addressSize);
387 cmd.NbData = length;
389 quadSpiSelectDevice(instance);
391 status = HAL_QSPI_Command(&quadSpiDevice[device].hquadSpi, &cmd, QUADSPI_DEFAULT_TIMEOUT);
392 bool timeout = (status != HAL_OK);
393 if (!timeout) {
394 status = HAL_QSPI_Receive(&quadSpiDevice[device].hquadSpi, in, QUADSPI_DEFAULT_TIMEOUT);
395 timeout = (status != HAL_OK);
398 quadSpiDeselectDevice(instance);
400 if (timeout) {
401 quadSpiTimeoutUserCallback(instance);
402 return false;
405 return true;
407 bool quadSpiTransmitWithAddress1LINE(QUADSPI_TypeDef *instance, uint8_t instruction, uint8_t dummyCycles, uint32_t address, uint8_t addressSize, const uint8_t *out, int length)
409 QUADSPIDevice device = quadSpiDeviceByInstance(instance);
410 HAL_StatusTypeDef status;
412 QSPI_CommandTypeDef cmd;
413 cmd.InstructionMode = QSPI_INSTRUCTION_1_LINE;
414 cmd.AddressMode = QSPI_ADDRESS_1_LINE;
415 cmd.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
416 cmd.DataMode = QSPI_DATA_1_LINE;
417 cmd.DummyCycles = dummyCycles;
418 cmd.DdrMode = QSPI_DDR_MODE_DISABLE;
419 cmd.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;
420 cmd.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;
422 cmd.Instruction = instruction;
423 cmd.Address = address;
424 cmd.AddressSize = quadSpi_addressSizeFromValue(addressSize);
425 cmd.NbData = length;
427 quadSpiSelectDevice(instance);
429 status = HAL_QSPI_Command(&quadSpiDevice[device].hquadSpi, &cmd, QUADSPI_DEFAULT_TIMEOUT);
430 bool timeout = (status != HAL_OK);
432 if (!timeout) {
433 status = HAL_QSPI_Transmit(&quadSpiDevice[device].hquadSpi, (uint8_t *)out, QUADSPI_DEFAULT_TIMEOUT);
434 timeout = (status != HAL_OK);
437 quadSpiDeselectDevice(instance);
439 if (timeout) {
440 quadSpiTimeoutUserCallback(instance);
441 return false;
444 return true;
447 bool quadSpiTransmitWithAddress4LINES(QUADSPI_TypeDef *instance, uint8_t instruction, uint8_t dummyCycles, uint32_t address, uint8_t addressSize, const uint8_t *out, int length)
449 QUADSPIDevice device = quadSpiDeviceByInstance(instance);
450 HAL_StatusTypeDef status;
452 QSPI_CommandTypeDef cmd;
453 cmd.InstructionMode = QSPI_INSTRUCTION_1_LINE;
454 cmd.AddressMode = QSPI_ADDRESS_1_LINE;
455 cmd.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
456 cmd.DataMode = QSPI_DATA_4_LINES;
457 cmd.DummyCycles = dummyCycles;
458 cmd.DdrMode = QSPI_DDR_MODE_DISABLE;
459 cmd.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;
460 cmd.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;
462 cmd.Instruction = instruction;
463 cmd.Address = address;
464 cmd.AddressSize = quadSpi_addressSizeFromValue(addressSize);
465 cmd.NbData = length;
467 quadSpiSelectDevice(instance);
469 status = HAL_QSPI_Command(&quadSpiDevice[device].hquadSpi, &cmd, QUADSPI_DEFAULT_TIMEOUT);
470 bool timeout = (status != HAL_OK);
472 if (!timeout) {
473 status = HAL_QSPI_Transmit(&quadSpiDevice[device].hquadSpi, (uint8_t *)out, QUADSPI_DEFAULT_TIMEOUT);
474 timeout = (status != HAL_OK);
477 quadSpiDeselectDevice(instance);
479 if (timeout) {
480 quadSpiTimeoutUserCallback(instance);
481 return false;
484 return true;
487 bool quadSpiInstructionWithAddress1LINE(QUADSPI_TypeDef *instance, uint8_t instruction, uint8_t dummyCycles, uint32_t address, uint8_t addressSize)
489 QUADSPIDevice device = quadSpiDeviceByInstance(instance);
490 HAL_StatusTypeDef status;
492 QSPI_CommandTypeDef cmd;
493 cmd.InstructionMode = QSPI_INSTRUCTION_1_LINE;
494 cmd.AddressMode = QSPI_ADDRESS_1_LINE;
495 cmd.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
496 cmd.DataMode = QSPI_DATA_NONE;
497 cmd.DummyCycles = dummyCycles;
498 cmd.DdrMode = QSPI_DDR_MODE_DISABLE;
499 cmd.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;
500 cmd.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;
502 cmd.Instruction = instruction;
503 cmd.Address = address;
504 cmd.AddressSize = quadSpi_addressSizeFromValue(addressSize);
505 cmd.NbData = 0;
507 quadSpiSelectDevice(instance);
509 status = HAL_QSPI_Command(&quadSpiDevice[device].hquadSpi, &cmd, QUADSPI_DEFAULT_TIMEOUT);
510 bool timeout = (status != HAL_OK);
512 quadSpiDeselectDevice(instance);
514 if (timeout) {
515 quadSpiTimeoutUserCallback(instance);
516 return false;
520 return true;
523 bool quadSpiInstructionWithData1LINE(QUADSPI_TypeDef *instance, uint8_t instruction, uint8_t dummyCycles, const uint8_t *out, int length)
525 QUADSPIDevice device = quadSpiDeviceByInstance(instance);
526 HAL_StatusTypeDef status;
528 QSPI_CommandTypeDef cmd;
529 cmd.InstructionMode = QSPI_INSTRUCTION_1_LINE;
530 cmd.AddressMode = QSPI_ADDRESS_NONE;
531 cmd.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
532 cmd.DataMode = QSPI_DATA_1_LINE;
533 cmd.DummyCycles = dummyCycles;
534 cmd.DdrMode = QSPI_DDR_MODE_DISABLE;
535 cmd.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;
536 cmd.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;
538 cmd.Instruction = instruction;
539 cmd.NbData = length;
541 quadSpiSelectDevice(instance);
543 status = HAL_QSPI_Command(&quadSpiDevice[device].hquadSpi, &cmd, QUADSPI_DEFAULT_TIMEOUT);
544 bool timeout =(status != HAL_OK);
546 if (!timeout) {
547 status = HAL_QSPI_Transmit(&quadSpiDevice[device].hquadSpi, (uint8_t *)out, QUADSPI_DEFAULT_TIMEOUT);
548 timeout = (status != HAL_OK);
551 quadSpiDeselectDevice(instance);
553 if (timeout) {
554 quadSpiTimeoutUserCallback(instance);
555 return false;
558 return true;
561 void quadSpiSetDivisor(QUADSPI_TypeDef *instance, uint16_t divisor)
563 QUADSPIDevice device = quadSpiDeviceByInstance(instance);
564 if (HAL_QSPI_DeInit(&quadSpiDevice[device].hquadSpi) != HAL_OK)
566 Error_Handler();
569 quadSpiDevice_t *quadSpi = &(quadSpiDevice[device]);
571 quadSpi->hquadSpi.Init.ClockPrescaler = divisor;
573 HAL_QSPI_Init(&quadSpi->hquadSpi);
575 #endif