Merge pull request #11198 from SteveCEvans/sce_rc2
[betaflight.git] / src / main / drivers / bus_quadspi_hal.c
blob655b2a1d601297d45ef21088b476e18936e55c2e
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 #include "pg/bus_quadspi.h"
40 static void Error_Handler(void) { while (1) { } }
42 void quadSpiInitDevice(QUADSPIDevice device)
44 quadSpiDevice_t *quadSpi = &(quadSpiDevice[device]);
46 // Enable QUADSPI clock
47 RCC_ClockCmd(quadSpi->rcc, ENABLE);
48 RCC_ResetCmd(quadSpi->rcc, ENABLE);
50 IOInit(IOGetByTag(quadSpi->clk), OWNER_QUADSPI_CLK, RESOURCE_INDEX(device));
51 IOInit(IOGetByTag(quadSpi->bk1IO0), OWNER_QUADSPI_BK1IO0, RESOURCE_INDEX(device));
52 IOInit(IOGetByTag(quadSpi->bk1IO1), OWNER_QUADSPI_BK1IO1, RESOURCE_INDEX(device));
53 IOInit(IOGetByTag(quadSpi->bk1IO2), OWNER_QUADSPI_BK1IO2, RESOURCE_INDEX(device));
54 IOInit(IOGetByTag(quadSpi->bk1IO3), OWNER_QUADSPI_BK1IO3, RESOURCE_INDEX(device));
55 IOInit(IOGetByTag(quadSpi->bk1CS), OWNER_QUADSPI_BK1CS, RESOURCE_INDEX(device));
57 IOInit(IOGetByTag(quadSpi->bk2IO0), OWNER_QUADSPI_BK2IO0, RESOURCE_INDEX(device));
58 IOInit(IOGetByTag(quadSpi->bk2IO1), OWNER_QUADSPI_BK2IO1, RESOURCE_INDEX(device));
59 IOInit(IOGetByTag(quadSpi->bk2IO2), OWNER_QUADSPI_BK2IO2, RESOURCE_INDEX(device));
60 IOInit(IOGetByTag(quadSpi->bk2IO3), OWNER_QUADSPI_BK2IO3, RESOURCE_INDEX(device));
61 IOInit(IOGetByTag(quadSpi->bk2CS), OWNER_QUADSPI_BK2CS, RESOURCE_INDEX(device));
63 #if defined(STM32H7)
64 // clock is only on AF9
65 // IO and CS lines are on AF9 and AF10
66 IOConfigGPIOAF(IOGetByTag(quadSpi->clk), QUADSPI_IO_AF_CLK_CFG, GPIO_AF9_QUADSPI);
67 IOConfigGPIOAF(IOGetByTag(quadSpi->bk1IO0), QUADSPI_IO_AF_BK_IO_CFG, quadSpi->bk1IO0AF);
68 IOConfigGPIOAF(IOGetByTag(quadSpi->bk1IO1), QUADSPI_IO_AF_BK_IO_CFG, quadSpi->bk1IO1AF);
69 IOConfigGPIOAF(IOGetByTag(quadSpi->bk1IO2), QUADSPI_IO_AF_BK_IO_CFG, quadSpi->bk1IO2AF);
70 IOConfigGPIOAF(IOGetByTag(quadSpi->bk1IO3), QUADSPI_IO_AF_BK_IO_CFG, quadSpi->bk1IO3AF);
71 IOConfigGPIOAF(IOGetByTag(quadSpi->bk2IO0), QUADSPI_IO_AF_BK_IO_CFG, quadSpi->bk2IO0AF);
72 IOConfigGPIOAF(IOGetByTag(quadSpi->bk2IO1), QUADSPI_IO_AF_BK_IO_CFG, quadSpi->bk2IO1AF);
73 IOConfigGPIOAF(IOGetByTag(quadSpi->bk2IO2), QUADSPI_IO_AF_BK_IO_CFG, quadSpi->bk2IO2AF);
74 IOConfigGPIOAF(IOGetByTag(quadSpi->bk2IO3), QUADSPI_IO_AF_BK_IO_CFG, quadSpi->bk2IO3AF);
76 if ((quadSpiConfig(device)->csFlags & QUADSPI_BK1_CS_MASK) == QUADSPI_BK1_CS_HARDWARE) {
77 IOConfigGPIOAF(IOGetByTag(quadSpi->bk1CS), QUADSPI_IO_AF_BK_CS_CFG, quadSpi->bk1CSAF);
78 } else {
79 IOConfigGPIO(IOGetByTag(quadSpi->bk1CS), QUADSPI_IO_BK_CS_CFG);
82 if ((quadSpiConfig(device)->csFlags & QUADSPI_BK2_CS_MASK) == QUADSPI_BK2_CS_HARDWARE) {
83 IOConfigGPIOAF(IOGetByTag(quadSpi->bk2CS), QUADSPI_IO_AF_BK_CS_CFG, quadSpi->bk2CSAF);
84 } else {
85 IOConfigGPIO(IOGetByTag(quadSpi->bk2CS), QUADSPI_IO_BK_CS_CFG);
87 #endif
89 quadSpi->hquadSpi.Instance = quadSpi->dev;
90 // DeInit QUADSPI hardware
91 HAL_QSPI_DeInit(&quadSpi->hquadSpi);
93 quadSpi->hquadSpi.Init.ClockPrescaler = QUADSPI_CLOCK_INITIALISATION;
94 quadSpi->hquadSpi.Init.FifoThreshold = 1;
95 quadSpi->hquadSpi.Init.SampleShifting = QSPI_SAMPLE_SHIFTING_NONE;
96 quadSpi->hquadSpi.Init.FlashSize = 23; // address bits + 1
97 quadSpi->hquadSpi.Init.ChipSelectHighTime = QSPI_CS_HIGH_TIME_1_CYCLE;
98 quadSpi->hquadSpi.Init.ClockMode = QSPI_CLOCK_MODE_0;
100 switch (quadSpiConfig(device)->mode) {
101 case QUADSPI_MODE_BK1_ONLY:
102 quadSpi->hquadSpi.Init.FlashID = QSPI_FLASH_ID_1;
103 quadSpi->hquadSpi.Init.DualFlash = QSPI_DUALFLASH_DISABLE;
104 break;
105 case QUADSPI_MODE_BK2_ONLY:
106 quadSpi->hquadSpi.Init.FlashID = QSPI_FLASH_ID_2;
107 quadSpi->hquadSpi.Init.DualFlash = QSPI_DUALFLASH_DISABLE;
108 break;
109 case QUADSPI_MODE_DUAL_FLASH:
110 quadSpi->hquadSpi.Init.DualFlash = QSPI_DUALFLASH_ENABLE;
111 break;
114 // Init QUADSPI hardware
115 if (HAL_QSPI_Init(&quadSpi->hquadSpi) != HAL_OK)
117 Error_Handler();
121 static const uint32_t quadSpi_addressSizeMap[] = {
122 QSPI_ADDRESS_8_BITS,
123 QSPI_ADDRESS_16_BITS,
124 QSPI_ADDRESS_24_BITS,
125 QSPI_ADDRESS_32_BITS
128 static uint32_t quadSpi_addressSizeFromValue(uint8_t addressSize)
130 return quadSpi_addressSizeMap[((addressSize + 1) / 8) - 1]; // rounds to nearest QSPI_ADDRESS_* value that will hold the address.
134 * Return true if the bus is currently in the middle of a transmission.
136 bool quadSpiIsBusBusy(QUADSPI_TypeDef *instance)
138 QUADSPIDevice device = quadSpiDeviceByInstance(instance);
139 if(quadSpiDevice[device].hquadSpi.State == HAL_QSPI_STATE_BUSY)
140 return true;
141 else
142 return false;
145 #define QUADSPI_DEFAULT_TIMEOUT 10
147 void quadSpiSelectDevice(QUADSPI_TypeDef *instance)
149 QUADSPIDevice device = quadSpiDeviceByInstance(instance);
151 IO_t bk1CS = IOGetByTag(quadSpiDevice[device].bk1CS);
152 IO_t bk2CS = IOGetByTag(quadSpiDevice[device].bk2CS);
154 switch(quadSpiConfig(device)->mode) {
155 case QUADSPI_MODE_DUAL_FLASH:
156 if ((quadSpiConfig(device)->csFlags & QUADSPI_BK1_CS_MASK) == QUADSPI_BK1_CS_SOFTWARE) {
157 IOLo(bk1CS);
159 if ((quadSpiConfig(device)->csFlags & QUADSPI_BK2_CS_MASK) == QUADSPI_BK2_CS_SOFTWARE) {
160 IOLo(bk2CS);
162 break;
163 case QUADSPI_MODE_BK1_ONLY:
164 if ((quadSpiConfig(device)->csFlags & QUADSPI_BK1_CS_MASK) == QUADSPI_BK1_CS_SOFTWARE) {
165 IOLo(bk1CS);
167 break;
168 case QUADSPI_MODE_BK2_ONLY:
169 if ((quadSpiConfig(device)->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 IO_t bk1CS = IOGetByTag(quadSpiDevice[device].bk1CS);
181 IO_t bk2CS = IOGetByTag(quadSpiDevice[device].bk2CS);
183 switch(quadSpiConfig(device)->mode) {
184 case QUADSPI_MODE_DUAL_FLASH:
185 if ((quadSpiConfig(device)->csFlags & QUADSPI_BK1_CS_MASK) == QUADSPI_BK1_CS_SOFTWARE) {
186 IOHi(bk1CS);
188 if ((quadSpiConfig(device)->csFlags & QUADSPI_BK2_CS_MASK) == QUADSPI_BK2_CS_SOFTWARE) {
189 IOHi(bk2CS);
191 break;
192 case QUADSPI_MODE_BK1_ONLY:
193 if ((quadSpiConfig(device)->csFlags & QUADSPI_BK1_CS_MASK) == QUADSPI_BK1_CS_SOFTWARE) {
194 IOHi(bk1CS);
196 break;
197 case QUADSPI_MODE_BK2_ONLY:
198 if ((quadSpiConfig(device)->csFlags & QUADSPI_BK2_CS_MASK) == QUADSPI_BK2_CS_SOFTWARE) {
199 IOHi(bk2CS);
201 break;
207 bool quadSpiTransmit1LINE(QUADSPI_TypeDef *instance, uint8_t instruction, uint8_t dummyCycles, const uint8_t *out, int length)
209 QUADSPIDevice device = quadSpiDeviceByInstance(instance);
210 HAL_StatusTypeDef status;
213 QSPI_CommandTypeDef cmd;
214 cmd.InstructionMode = QSPI_INSTRUCTION_1_LINE;
215 cmd.AddressMode = QSPI_ADDRESS_NONE;
216 cmd.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
217 cmd.DataMode = QSPI_DATA_NONE;
218 cmd.DummyCycles = dummyCycles;
219 cmd.DdrMode = QSPI_DDR_MODE_DISABLE;
220 cmd.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;
221 cmd.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;
223 cmd.Instruction = instruction;
224 cmd.NbData = length;
226 if (out) {
227 cmd.DataMode = QSPI_DATA_1_LINE;
230 quadSpiSelectDevice(instance);
232 status = HAL_QSPI_Command(&quadSpiDevice[device].hquadSpi, &cmd, QUADSPI_DEFAULT_TIMEOUT);
233 bool timeout = (status != HAL_OK);
234 if (!timeout) {
235 if (out && length > 0) {
236 status = HAL_QSPI_Transmit(&quadSpiDevice[device].hquadSpi, (uint8_t *)out, QUADSPI_DEFAULT_TIMEOUT);
237 timeout = (status != HAL_OK);
241 quadSpiDeselectDevice(instance);
243 if (timeout) {
244 quadSpiTimeoutUserCallback(instance);
245 return false;
248 return true;
251 bool quadSpiReceive1LINE(QUADSPI_TypeDef *instance, uint8_t instruction, uint8_t dummyCycles, uint8_t *in, int length)
253 QUADSPIDevice device = quadSpiDeviceByInstance(instance);
254 HAL_StatusTypeDef status;
256 QSPI_CommandTypeDef cmd;
257 cmd.InstructionMode = QSPI_INSTRUCTION_1_LINE;
258 cmd.AddressMode = QSPI_ADDRESS_NONE;
259 cmd.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
260 cmd.DataMode = QSPI_DATA_1_LINE;
261 cmd.DummyCycles = dummyCycles;
262 cmd.DdrMode = QSPI_DDR_MODE_DISABLE;
263 cmd.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;
264 cmd.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;
266 cmd.Instruction = instruction;
267 cmd.NbData = length;
269 quadSpiSelectDevice(instance);
271 status = HAL_QSPI_Command(&quadSpiDevice[device].hquadSpi, &cmd, QUADSPI_DEFAULT_TIMEOUT);
272 bool timeout = (status != HAL_OK);
273 if (!timeout) {
274 status = HAL_QSPI_Receive(&quadSpiDevice[device].hquadSpi, in, QUADSPI_DEFAULT_TIMEOUT);
276 timeout = (status != HAL_OK);
279 quadSpiDeselectDevice(instance);
281 if (timeout) {
282 quadSpiTimeoutUserCallback(instance);
283 return false;
286 return true;
289 bool quadSpiReceive4LINES(QUADSPI_TypeDef *instance, uint8_t instruction, uint8_t dummyCycles, uint8_t *in, int length)
291 QUADSPIDevice device = quadSpiDeviceByInstance(instance);
292 HAL_StatusTypeDef status;
294 QSPI_CommandTypeDef cmd;
295 cmd.InstructionMode = QSPI_INSTRUCTION_4_LINES;
296 cmd.AddressMode = QSPI_ADDRESS_NONE;
297 cmd.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
298 cmd.DataMode = QSPI_DATA_4_LINES;
299 cmd.DummyCycles = dummyCycles;
300 cmd.DdrMode = QSPI_DDR_MODE_DISABLE;
301 cmd.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;
302 cmd.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;
304 cmd.Instruction = instruction;
305 cmd.NbData = length;
307 quadSpiSelectDevice(instance);
309 status = HAL_QSPI_Command(&quadSpiDevice[device].hquadSpi, &cmd, QUADSPI_DEFAULT_TIMEOUT);
310 bool timeout = (status != HAL_OK);
311 if (!timeout) {
312 status = HAL_QSPI_Receive(&quadSpiDevice[device].hquadSpi, in, QUADSPI_DEFAULT_TIMEOUT);
314 timeout = (status != HAL_OK);
317 quadSpiDeselectDevice(instance);
319 if (timeout) {
320 quadSpiTimeoutUserCallback(instance);
321 return false;
324 return true;
327 bool quadSpiReceiveWithAddress1LINE(QUADSPI_TypeDef *instance, uint8_t instruction, uint8_t dummyCycles, uint32_t address, uint8_t addressSize, uint8_t *in, int length)
329 QUADSPIDevice device = quadSpiDeviceByInstance(instance);
330 HAL_StatusTypeDef status;
332 QSPI_CommandTypeDef cmd;
333 cmd.InstructionMode = QSPI_INSTRUCTION_1_LINE;
334 cmd.AddressMode = QSPI_ADDRESS_1_LINE;
335 cmd.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
336 cmd.DataMode = QSPI_DATA_1_LINE;
337 cmd.DummyCycles = dummyCycles;
338 cmd.DdrMode = QSPI_DDR_MODE_DISABLE;
339 cmd.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;
340 cmd.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;
342 cmd.Instruction = instruction;
343 cmd.Address = address;
344 cmd.AddressSize = quadSpi_addressSizeFromValue(addressSize);
345 cmd.NbData = length;
347 quadSpiSelectDevice(instance);
349 status = HAL_QSPI_Command(&quadSpiDevice[device].hquadSpi, &cmd, QUADSPI_DEFAULT_TIMEOUT);
350 bool timeout = (status != HAL_OK);
351 if (!timeout) {
352 status = HAL_QSPI_Receive(&quadSpiDevice[device].hquadSpi, in, QUADSPI_DEFAULT_TIMEOUT);
353 timeout = (status != HAL_OK);
356 quadSpiDeselectDevice(instance);
358 if (timeout) {
359 quadSpiTimeoutUserCallback(instance);
360 return false;
363 return true;
367 bool quadSpiReceiveWithAddress4LINES(QUADSPI_TypeDef *instance, uint8_t instruction, uint8_t dummyCycles, uint32_t address, uint8_t addressSize, uint8_t *in, int length)
369 QUADSPIDevice device = quadSpiDeviceByInstance(instance);
370 HAL_StatusTypeDef status;
372 QSPI_CommandTypeDef cmd;
373 cmd.InstructionMode = QSPI_INSTRUCTION_1_LINE;
374 cmd.AddressMode = QSPI_ADDRESS_1_LINE;
375 cmd.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
376 cmd.DataMode = QSPI_DATA_4_LINES;
377 cmd.DummyCycles = dummyCycles;
378 cmd.DdrMode = QSPI_DDR_MODE_DISABLE;
379 cmd.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;
380 cmd.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;
382 cmd.Instruction = instruction;
383 cmd.Address = address;
384 cmd.AddressSize = quadSpi_addressSizeFromValue(addressSize);
385 cmd.NbData = length;
387 quadSpiSelectDevice(instance);
389 status = HAL_QSPI_Command(&quadSpiDevice[device].hquadSpi, &cmd, QUADSPI_DEFAULT_TIMEOUT);
390 bool timeout = (status != HAL_OK);
391 if (!timeout) {
392 status = HAL_QSPI_Receive(&quadSpiDevice[device].hquadSpi, in, QUADSPI_DEFAULT_TIMEOUT);
393 timeout = (status != HAL_OK);
396 quadSpiDeselectDevice(instance);
398 if (timeout) {
399 quadSpiTimeoutUserCallback(instance);
400 return false;
403 return true;
405 bool quadSpiTransmitWithAddress1LINE(QUADSPI_TypeDef *instance, uint8_t instruction, uint8_t dummyCycles, uint32_t address, uint8_t addressSize, const uint8_t *out, int length)
407 QUADSPIDevice device = quadSpiDeviceByInstance(instance);
408 HAL_StatusTypeDef status;
410 QSPI_CommandTypeDef cmd;
411 cmd.InstructionMode = QSPI_INSTRUCTION_1_LINE;
412 cmd.AddressMode = QSPI_ADDRESS_1_LINE;
413 cmd.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
414 cmd.DataMode = QSPI_DATA_1_LINE;
415 cmd.DummyCycles = dummyCycles;
416 cmd.DdrMode = QSPI_DDR_MODE_DISABLE;
417 cmd.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;
418 cmd.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;
420 cmd.Instruction = instruction;
421 cmd.Address = address;
422 cmd.AddressSize = quadSpi_addressSizeFromValue(addressSize);
423 cmd.NbData = length;
425 quadSpiSelectDevice(instance);
427 status = HAL_QSPI_Command(&quadSpiDevice[device].hquadSpi, &cmd, QUADSPI_DEFAULT_TIMEOUT);
428 bool timeout = (status != HAL_OK);
430 if (!timeout) {
431 status = HAL_QSPI_Transmit(&quadSpiDevice[device].hquadSpi, (uint8_t *)out, QUADSPI_DEFAULT_TIMEOUT);
432 timeout = (status != HAL_OK);
435 quadSpiDeselectDevice(instance);
437 if (timeout) {
438 quadSpiTimeoutUserCallback(instance);
439 return false;
442 return true;
445 bool quadSpiTransmitWithAddress4LINES(QUADSPI_TypeDef *instance, uint8_t instruction, uint8_t dummyCycles, uint32_t address, uint8_t addressSize, const uint8_t *out, int length)
447 QUADSPIDevice device = quadSpiDeviceByInstance(instance);
448 HAL_StatusTypeDef status;
450 QSPI_CommandTypeDef cmd;
451 cmd.InstructionMode = QSPI_INSTRUCTION_1_LINE;
452 cmd.AddressMode = QSPI_ADDRESS_1_LINE;
453 cmd.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
454 cmd.DataMode = QSPI_DATA_4_LINES;
455 cmd.DummyCycles = dummyCycles;
456 cmd.DdrMode = QSPI_DDR_MODE_DISABLE;
457 cmd.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;
458 cmd.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;
460 cmd.Instruction = instruction;
461 cmd.Address = address;
462 cmd.AddressSize = quadSpi_addressSizeFromValue(addressSize);
463 cmd.NbData = length;
465 quadSpiSelectDevice(instance);
467 status = HAL_QSPI_Command(&quadSpiDevice[device].hquadSpi, &cmd, QUADSPI_DEFAULT_TIMEOUT);
468 bool timeout = (status != HAL_OK);
470 if (!timeout) {
471 status = HAL_QSPI_Transmit(&quadSpiDevice[device].hquadSpi, (uint8_t *)out, QUADSPI_DEFAULT_TIMEOUT);
472 timeout = (status != HAL_OK);
475 quadSpiDeselectDevice(instance);
477 if (timeout) {
478 quadSpiTimeoutUserCallback(instance);
479 return false;
482 return true;
485 bool quadSpiInstructionWithAddress1LINE(QUADSPI_TypeDef *instance, uint8_t instruction, uint8_t dummyCycles, uint32_t address, uint8_t addressSize)
487 QUADSPIDevice device = quadSpiDeviceByInstance(instance);
488 HAL_StatusTypeDef status;
490 QSPI_CommandTypeDef cmd;
491 cmd.InstructionMode = QSPI_INSTRUCTION_1_LINE;
492 cmd.AddressMode = QSPI_ADDRESS_1_LINE;
493 cmd.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
494 cmd.DataMode = QSPI_DATA_NONE;
495 cmd.DummyCycles = dummyCycles;
496 cmd.DdrMode = QSPI_DDR_MODE_DISABLE;
497 cmd.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;
498 cmd.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;
500 cmd.Instruction = instruction;
501 cmd.Address = address;
502 cmd.AddressSize = quadSpi_addressSizeFromValue(addressSize);
503 cmd.NbData = 0;
505 quadSpiSelectDevice(instance);
507 status = HAL_QSPI_Command(&quadSpiDevice[device].hquadSpi, &cmd, QUADSPI_DEFAULT_TIMEOUT);
508 bool timeout = (status != HAL_OK);
510 quadSpiDeselectDevice(instance);
512 if (timeout) {
513 quadSpiTimeoutUserCallback(instance);
514 return false;
518 return true;
521 bool quadSpiInstructionWithData1LINE(QUADSPI_TypeDef *instance, uint8_t instruction, uint8_t dummyCycles, const uint8_t *out, int length)
523 QUADSPIDevice device = quadSpiDeviceByInstance(instance);
524 HAL_StatusTypeDef status;
526 QSPI_CommandTypeDef cmd;
527 cmd.InstructionMode = QSPI_INSTRUCTION_1_LINE;
528 cmd.AddressMode = QSPI_ADDRESS_NONE;
529 cmd.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
530 cmd.DataMode = QSPI_DATA_1_LINE;
531 cmd.DummyCycles = dummyCycles;
532 cmd.DdrMode = QSPI_DDR_MODE_DISABLE;
533 cmd.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;
534 cmd.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;
536 cmd.Instruction = instruction;
537 cmd.NbData = length;
539 quadSpiSelectDevice(instance);
541 status = HAL_QSPI_Command(&quadSpiDevice[device].hquadSpi, &cmd, QUADSPI_DEFAULT_TIMEOUT);
542 bool timeout =(status != HAL_OK);
544 if (!timeout) {
545 status = HAL_QSPI_Transmit(&quadSpiDevice[device].hquadSpi, (uint8_t *)out, QUADSPI_DEFAULT_TIMEOUT);
546 timeout = (status != HAL_OK);
549 quadSpiDeselectDevice(instance);
551 if (timeout) {
552 quadSpiTimeoutUserCallback(instance);
553 return false;
556 return true;
559 void quadSpiSetDivisor(QUADSPI_TypeDef *instance, uint16_t divisor)
561 QUADSPIDevice device = quadSpiDeviceByInstance(instance);
562 if (HAL_QSPI_DeInit(&quadSpiDevice[device].hquadSpi) != HAL_OK)
564 Error_Handler();
567 quadSpiDevice_t *quadSpi = &(quadSpiDevice[device]);
569 quadSpi->hquadSpi.Init.ClockPrescaler = divisor;
571 HAL_QSPI_Init(&quadSpi->hquadSpi);
573 #endif