Merge pull request #9742 from mikeller/fix_spi_transaction_support
[betaflight.git] / src / main / drivers / bus_quadspi.h
blob4e0e03ffe0d5767292ef3283de31d35b8d30c3a3
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 #pragma once
25 #include "drivers/io_types.h"
26 #include "drivers/rcc_types.h"
28 #include "pg/pg.h"
29 #include "pg/pg_ids.h"
32 * Quad SPI supports 1/2/4 wire modes
34 * 1LINE is like SPI MISO/MOSI using D0 (MOSI)/D1(MISO).
35 * 2LINE uses D0, D1 (bidirectional).
36 * 4LINE uses D0..D3 (bidirectional)
38 * See ST Micros' AN4760 "Quad-SPI (QSPI) interface on STM32 microcontrollers"
41 #ifdef USE_QUADSPI
43 #if !defined(STM32H7)
44 #error Quad SPI unsupported on this MCU
45 #endif
47 #define QUADSPI_IO_AF_BK_IO_CFG IO_CONFIG(GPIO_MODE_AF_PP, GPIO_SPEED_FREQ_VERY_HIGH, GPIO_NOPULL)
48 #define QUADSPI_IO_AF_CLK_CFG IO_CONFIG(GPIO_MODE_AF_PP, GPIO_SPEED_FREQ_VERY_HIGH, GPIO_NOPULL)
49 #define QUADSPI_IO_AF_BK_CS_CFG IO_CONFIG(GPIO_MODE_AF_PP, GPIO_SPEED_FREQ_VERY_HIGH, GPIO_PULLUP)
50 #define QUADSPI_IO_BK_CS_CFG IO_CONFIG(GPIO_MODE_OUTPUT_PP, GPIO_SPEED_FREQ_HIGH, GPIO_PULLUP)
52 typedef enum {
53 QUADSPI_CLOCK_INITIALIZATION = 256,
54 /* QSPI freq = CLK /(1 + ClockPrescaler) = 200 MHz/(1+x) */
55 QUADSPI_CLOCK_INITIALISATION = 255, // 0.78125 Mhz
56 QUADSPI_CLOCK_SLOW = 19, // 10.00000 Mhz
57 QUADSPI_CLOCK_STANDARD = 9, // 20.00000 MHz
58 QUADSPI_CLOCK_FAST = 3, // 50.00000 MHz
59 QUADSPI_CLOCK_ULTRAFAST = 1 //100.00000 MHz
60 } QUADSPIClockDivider_e;
62 typedef enum QUADSPIDevice {
63 QUADSPIINVALID = -1,
64 QUADSPIDEV_1 = 0,
65 } QUADSPIDevice;
67 #define QUADSPIDEV_COUNT 1
69 // Macros to convert between CLI bus number and SPIDevice.
70 #define QUADSPI_CFG_TO_DEV(x) ((x) - 1)
71 #define QUADSPI_DEV_TO_CFG(x) ((x) + 1)
73 typedef enum {
74 QUADSPI_MODE_BK1_ONLY = 0,
75 QUADSPI_MODE_BK2_ONLY,
76 QUADSPI_MODE_DUAL_FLASH,
77 } quadSpiMode_e;
80 // QUADSPI1_CS_FLAGS
82 #define QUADSPI_BK1_CS_MASK ((1 << 1) | (1 << 0))
84 #define QUADSPI_BK1_CS_NONE ((0 << 1) | (0 << 0))
85 #define QUADSPI_BK1_CS_HARDWARE ((0 << 1) | (1 << 0)) // pin must support QSPI Alternate function for BK1_NCS
86 #define QUADSPI_BK1_CS_SOFTWARE ((1 << 1) | (0 << 0)) // use any GPIO pin for BK1 CS
88 #define QUADSPI_BK2_CS_MASK ((1 << 3) | (1 << 2))
90 #define QUADSPI_BK2_CS_NONE ((0 << 3) | (0 << 2))
91 #define QUADSPI_BK2_CS_HARDWARE ((0 << 3) | (1 << 2)) // pin must support QSPI Alternate function for BK2_NCS
92 #define QUADSPI_BK2_CS_SOFTWARE ((1 << 3) | (0 << 2)) // use any GPIO pin for BK2 CS
94 #define QUADSPI_CS_MODE_MASK (1 << 4)
96 #define QUADSPI_CS_MODE_SEPARATE (0 << 4)
97 #define QUADSPI_CS_MODE_LINKED (1 << 4)
99 // H7 QSPI notes:
100 // Hardware supports BK1 and BK2 connected to both flash chips when using DUAL FLASH mode.
101 // Hardware does NOT support using BK1_NCS for single flash chip on BK2.
102 // It's possible to use BK1_NCS for single chip on BK2 using software CS via QUADSPI_BK2_CS_SOFTWARE
105 void quadSpiPreInit(void);
107 bool quadSpiInit(QUADSPIDevice device);
108 void quadSpiSetDivisor(QUADSPI_TypeDef *instance, uint16_t divisor);
110 bool quadSpiTransmit1LINE(QUADSPI_TypeDef *instance, uint8_t instruction, uint8_t dummyCycles, const uint8_t *out, int length);
111 bool quadSpiReceive1LINE(QUADSPI_TypeDef *instance, uint8_t instruction, uint8_t dummyCycles, uint8_t *in, int length);
113 bool quadSpiInstructionWithData1LINE(QUADSPI_TypeDef *instance, uint8_t instruction, uint8_t dummyCycles, const uint8_t *out, int length);
115 bool quadSpiReceiveWithAddress1LINE(QUADSPI_TypeDef *instance, uint8_t instruction, uint8_t dummyCycles, uint32_t address, uint8_t addressSize, uint8_t *in, int length);
116 bool quadSpiReceiveWithAddress4LINES(QUADSPI_TypeDef *instance, uint8_t instruction, uint8_t dummyCycles, uint32_t address, uint8_t addressSize, uint8_t *in, int length);
117 bool quadSpiTransmitWithAddress1LINE(QUADSPI_TypeDef *instance, uint8_t instruction, uint8_t dummyCycles, uint32_t address, uint8_t addressSize, const uint8_t *out, int length);
120 bool quadSpiInstructionWithAddress1LINE(QUADSPI_TypeDef *instance, uint8_t instruction, uint8_t dummyCycles, uint32_t address, uint8_t addressSize);
122 //bool quadSpiIsBusBusy(SPI_TypeDef *instance);
124 uint16_t quadSpiGetErrorCounter(QUADSPI_TypeDef *instance);
125 void quadSpiResetErrorCounter(QUADSPI_TypeDef *instance);
127 QUADSPIDevice quadSpiDeviceByInstance(QUADSPI_TypeDef *instance);
128 QUADSPI_TypeDef *quadSpiInstanceByDevice(QUADSPIDevice device);
131 // Config
134 struct quadSpiConfig_s;
135 void quadSpiPinConfigure(const struct quadSpiConfig_s *pConfig);
137 #endif