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
25 #include "drivers/io_types.h"
26 #include "drivers/rcc_types.h"
29 #include "pg/pg_ids.h"
32 * Quad SPI supports 1/2/4 wire modes
34 * 1LINE is like SPI SDI/SDO using D0 (SDO)/D1(SDI).
35 * 2LINE uses D0, D1 (bidirectional).
36 * 4LINE uses D0..D3 (bidirectional)
38 * See ST Micros' AN4760 "Quad-SPI (QSPI) interface on STM32 microcontrollers"
44 #error Quad SPI unsupported on this MCU
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)
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
{
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)
74 QUADSPI_MODE_BK1_ONLY
= 0,
75 QUADSPI_MODE_BK2_ONLY
,
76 QUADSPI_MODE_DUAL_FLASH
,
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)
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
104 void quadSpiPreInit(void);
106 bool quadSpiInit(QUADSPIDevice device
);
107 void quadSpiSetDivisor(QUADSPI_TypeDef
*instance
, uint16_t divisor
);
109 bool quadSpiTransmit1LINE(QUADSPI_TypeDef
*instance
, uint8_t instruction
, uint8_t dummyCycles
, const uint8_t *out
, int length
);
110 bool quadSpiReceive1LINE(QUADSPI_TypeDef
*instance
, uint8_t instruction
, uint8_t dummyCycles
, uint8_t *in
, int length
);
111 bool quadSpiReceive4LINES(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
);
118 bool quadSpiTransmitWithAddress4LINES(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
);
134 struct quadSpiConfig_s
;
135 void quadSpiPinConfigure(const struct quadSpiConfig_s
*pConfig
);