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 * Quad SPI supports 1/2/4 wire modes
31 * 1LINE is like SPI MISO/MOSI using D0 (MOSI)/D1(MISO).
32 * 2LINE uses D0, D1 (bidirectional).
33 * 4LINE uses D0..D3 (bidirectional)
35 * See ST Micros' AN4760 "Quad-SPI (QSPI) interface on STM32 microcontrollers"
41 #error Quad SPI unsupported on this MCU
44 #define QUADSPI_IO_AF_BK_IO_CFG IO_CONFIG(GPIO_MODE_AF_PP, GPIO_SPEED_FREQ_VERY_HIGH, GPIO_NOPULL)
45 #define QUADSPI_IO_AF_CLK_CFG IO_CONFIG(GPIO_MODE_AF_PP, GPIO_SPEED_FREQ_VERY_HIGH, GPIO_NOPULL)
46 #define QUADSPI_IO_AF_BK_CS_CFG IO_CONFIG(GPIO_MODE_AF_PP, GPIO_SPEED_FREQ_VERY_HIGH, GPIO_PULLUP)
47 #define QUADSPI_IO_BK_CS_CFG IO_CONFIG(GPIO_MODE_OUTPUT_PP, GPIO_SPEED_FREQ_HIGH, GPIO_PULLUP)
50 /* QSPI freq = CLK /(1 + ClockPrescaler) = 200 MHz/(1+x) */
51 QUADSPI_CLOCK_INITIALISATION
= 255, // 0.78125 Mhz
52 QUADSPI_CLOCK_SLOW
= 19, // 10.00000 Mhz
53 QUADSPI_CLOCK_STANDARD
= 9, // 20.00000 MHz
54 QUADSPI_CLOCK_FAST
= 3, // 50.00000 MHz
55 QUADSPI_CLOCK_ULTRAFAST
= 1 //100.00000 MHz
56 } QUADSPIClockDivider_e
;
58 typedef enum QUADSPIDevice
{
63 #define QUADSPIDEV_COUNT 1
65 // Macros to convert between CLI bus number and SPIDevice.
66 #define QUADSPI_CFG_TO_DEV(x) ((x) - 1)
67 #define QUADSPI_DEV_TO_CFG(x) ((x) + 1)
70 QUADSPI_MODE_BK1_ONLY
= 0,
71 QUADSPI_MODE_BK2_ONLY
,
72 QUADSPI_MODE_DUAL_FLASH
,
78 #define QUADSPI_BK1_CS_MASK ((1 << 1) | (1 << 0))
80 #define QUADSPI_BK1_CS_NONE ((0 << 1) | (0 << 0))
81 #define QUADSPI_BK1_CS_HARDWARE ((0 << 1) | (1 << 0)) // pin must support QSPI Alternate function for BK1_NCS
82 #define QUADSPI_BK1_CS_SOFTWARE ((1 << 1) | (0 << 0)) // use any GPIO pin for BK1 CS
84 #define QUADSPI_BK2_CS_MASK ((1 << 3) | (1 << 2))
86 #define QUADSPI_BK2_CS_NONE ((0 << 3) | (0 << 2))
87 #define QUADSPI_BK2_CS_HARDWARE ((0 << 3) | (1 << 2)) // pin must support QSPI Alternate function for BK2_NCS
88 #define QUADSPI_BK2_CS_SOFTWARE ((1 << 3) | (0 << 2)) // use any GPIO pin for BK2 CS
90 #define QUADSPI_CS_MODE_MASK (1 << 4)
92 #define QUADSPI_CS_MODE_SEPARATE (0 << 4)
93 #define QUADSPI_CS_MODE_LINKED (1 << 4)
96 // Hardware supports BK1 and BK2 connected to both flash chips when using DUAL FLASH mode.
97 // Hardware does NOT support using BK1_NCS for single flash chip on BK2.
98 // It's possible to use BK1_NCS for single chip on BK2 using software CS via QUADSPI_BK2_CS_SOFTWARE
101 void quadSpiPreInit(void);
103 bool quadSpiInit(QUADSPIDevice device
);
104 void quadSpiSetDivisor(QUADSPI_TypeDef
*instance
, uint16_t divisor
);
106 bool quadSpiTransmit1LINE(QUADSPI_TypeDef
*instance
, uint8_t instruction
, uint8_t dummyCycles
, const uint8_t *out
, int length
);
107 bool quadSpiReceive1LINE(QUADSPI_TypeDef
*instance
, uint8_t instruction
, uint8_t dummyCycles
, uint8_t *in
, int length
);
108 bool quadSpiReceive4LINES(QUADSPI_TypeDef
*instance
, uint8_t instruction
, uint8_t dummyCycles
, uint8_t *in
, int length
);
110 bool quadSpiInstructionWithData1LINE(QUADSPI_TypeDef
*instance
, uint8_t instruction
, uint8_t dummyCycles
, const uint8_t *out
, int length
);
112 bool quadSpiReceiveWithAddress1LINE(QUADSPI_TypeDef
*instance
, uint8_t instruction
, uint8_t dummyCycles
, uint32_t address
, uint8_t addressSize
, uint8_t *in
, int length
);
113 bool quadSpiReceiveWithAddress4LINES(QUADSPI_TypeDef
*instance
, uint8_t instruction
, uint8_t dummyCycles
, uint32_t address
, uint8_t addressSize
, uint8_t *in
, int length
);
114 bool quadSpiTransmitWithAddress1LINE(QUADSPI_TypeDef
*instance
, uint8_t instruction
, uint8_t dummyCycles
, uint32_t address
, uint8_t addressSize
, const uint8_t *out
, int length
);
115 bool quadSpiTransmitWithAddress4LINES(QUADSPI_TypeDef
*instance
, uint8_t instruction
, uint8_t dummyCycles
, uint32_t address
, uint8_t addressSize
, const uint8_t *out
, int length
);
118 bool quadSpiInstructionWithAddress1LINE(QUADSPI_TypeDef
*instance
, uint8_t instruction
, uint8_t dummyCycles
, uint32_t address
, uint8_t addressSize
);
120 //bool quadSpiIsBusBusy(SPI_TypeDef *instance);
122 uint16_t quadSpiGetErrorCounter(QUADSPI_TypeDef
*instance
);
123 void quadSpiResetErrorCounter(QUADSPI_TypeDef
*instance
);
125 QUADSPIDevice
quadSpiDeviceByInstance(QUADSPI_TypeDef
*instance
);
126 QUADSPI_TypeDef
*quadSpiInstanceByDevice(QUADSPIDevice device
);
132 typedef struct quadSpiConfig_s
{
133 QUADSPIDevice device
;
136 // Note: Either or both CS pin may be used in DUAL_FLASH mode, any unused pins should be IO_NONE
151 // CS pins can be under software control, useful when using BK1CS as the CS pin for BK2 in non-DUAL-FLASH mode.
155 const quadSpiConfig_t
* getQuadSpiConfig(QUADSPIDevice device
);
156 void quadSpiPinConfigure(QUADSPIDevice device
);