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 * HAL version resurrected from v3.1.7 (by jflyper)
32 #include "bus_spi_impl.h"
39 void spiInitDevice(SPIDevice device
, bool leadingEdge
)
41 spiDevice_t
*spi
= &(spiDevice
[device
]);
47 spi
->leadingEdge
= leadingEdge
;
50 RCC_ClockCmd(spi
->rcc
, ENABLE
);
51 RCC_ResetCmd(spi
->rcc
, ENABLE
);
53 IOInit(IOGetByTag(spi
->sck
), OWNER_SPI_SCK
, RESOURCE_INDEX(device
));
54 IOInit(IOGetByTag(spi
->miso
), OWNER_SPI_MISO
, RESOURCE_INDEX(device
));
55 IOInit(IOGetByTag(spi
->mosi
), OWNER_SPI_MOSI
, RESOURCE_INDEX(device
));
58 IOConfigGPIOAF(IOGetByTag(spi
->sck
), SPI_IO_AF_CFG
, spi
->af
);
59 IOConfigGPIOAF(IOGetByTag(spi
->miso
), SPI_IO_AF_CFG
, spi
->af
);
60 IOConfigGPIOAF(IOGetByTag(spi
->mosi
), SPI_IO_AF_CFG
, spi
->af
);
63 #if defined(STM32F4) || defined(STM32F7) || defined(STM32H7) || defined(STM32G4)
64 IOConfigGPIOAF(IOGetByTag(spi
->sck
), spi
->leadingEdge
? SPI_IO_AF_SCK_CFG_LOW
: SPI_IO_AF_SCK_CFG_HIGH
, spi
->sckAF
);
65 IOConfigGPIOAF(IOGetByTag(spi
->miso
), SPI_IO_AF_MISO_CFG
, spi
->misoAF
);
66 IOConfigGPIOAF(IOGetByTag(spi
->mosi
), SPI_IO_AF_CFG
, spi
->mosiAF
);
69 #if defined(STM32F10X)
70 IOConfigGPIO(IOGetByTag(spi
->sck
), SPI_IO_AF_SCK_CFG
);
71 IOConfigGPIO(IOGetByTag(spi
->miso
), SPI_IO_AF_MISO_CFG
);
72 IOConfigGPIO(IOGetByTag(spi
->mosi
), SPI_IO_AF_MOSI_CFG
);
75 spi
->hspi
.Instance
= spi
->dev
;
76 // DeInit SPI hardware
77 HAL_SPI_DeInit(&spi
->hspi
);
79 spi
->hspi
.Init
.Mode
= SPI_MODE_MASTER
;
80 spi
->hspi
.Init
.Direction
= SPI_DIRECTION_2LINES
;
81 spi
->hspi
.Init
.DataSize
= SPI_DATASIZE_8BIT
;
82 spi
->hspi
.Init
.NSS
= SPI_NSS_SOFT
;
83 spi
->hspi
.Init
.FirstBit
= SPI_FIRSTBIT_MSB
;
84 spi
->hspi
.Init
.CRCPolynomial
= 7;
85 spi
->hspi
.Init
.BaudRatePrescaler
= SPI_BAUDRATEPRESCALER_256
;
86 spi
->hspi
.Init
.CRCCalculation
= SPI_CRCCALCULATION_DISABLE
;
87 spi
->hspi
.Init
.TIMode
= SPI_TIMODE_DISABLED
;
89 spi
->hspi
.Init
.FifoThreshold
= SPI_FIFO_THRESHOLD_01DATA
;
90 spi
->hspi
.Init
.MasterKeepIOState
= SPI_MASTER_KEEP_IO_STATE_ENABLE
; /* Recommanded setting to avoid glitches */
93 if (spi
->leadingEdge
) {
94 spi
->hspi
.Init
.CLKPolarity
= SPI_POLARITY_LOW
;
95 spi
->hspi
.Init
.CLKPhase
= SPI_PHASE_1EDGE
;
98 spi
->hspi
.Init
.CLKPolarity
= SPI_POLARITY_HIGH
;
99 spi
->hspi
.Init
.CLKPhase
= SPI_PHASE_2EDGE
;
103 HAL_SPI_Init(&spi
->hspi
);
106 // return uint8_t value or -1 when failure
107 uint8_t spiTransferByte(SPI_TypeDef
*instance
, uint8_t out
)
111 spiTransfer(instance
, &out
, &in
, 1);
116 * Return true if the bus is currently in the middle of a transmission.
118 bool spiIsBusBusy(SPI_TypeDef
*instance
)
120 SPIDevice device
= spiDeviceByInstance(instance
);
121 if(spiDevice
[device
].hspi
.State
== HAL_SPI_STATE_BUSY
)
127 bool spiTransfer(SPI_TypeDef
*instance
, const uint8_t *out
, uint8_t *in
, int len
)
129 SPIDevice device
= spiDeviceByInstance(instance
);
130 HAL_StatusTypeDef status
;
132 #define SPI_DEFAULT_TIMEOUT 10
136 status
= HAL_SPI_Transmit(&spiDevice
[device
].hspi
, out
, len
, SPI_DEFAULT_TIMEOUT
);
139 status
= HAL_SPI_Receive(&spiDevice
[device
].hspi
, in
, len
, SPI_DEFAULT_TIMEOUT
);
142 status
= HAL_SPI_TransmitReceive(&spiDevice
[device
].hspi
, out
, in
, len
, SPI_DEFAULT_TIMEOUT
);
145 if(status
!= HAL_OK
) {
146 spiTimeoutUserCallback(instance
);
152 // Position of Prescaler bits are different from MCU to MCU
154 static uint32_t baudRatePrescaler
[8] = {
155 SPI_BAUDRATEPRESCALER_2
,
156 SPI_BAUDRATEPRESCALER_4
,
157 SPI_BAUDRATEPRESCALER_8
,
158 SPI_BAUDRATEPRESCALER_16
,
159 SPI_BAUDRATEPRESCALER_32
,
160 SPI_BAUDRATEPRESCALER_64
,
161 SPI_BAUDRATEPRESCALER_128
,
162 SPI_BAUDRATEPRESCALER_256
,
165 void spiSetDivisor(SPI_TypeDef
*instance
, uint16_t divisor
)
167 SPIDevice device
= spiDeviceByInstance(instance
);
169 HAL_SPI_DeInit(&spiDevice
[device
].hspi
);
171 spiDevice_t
*spi
= &(spiDevice
[device
]);
173 int prescalerIndex
= ffs(divisor
) - 2; // prescaler begins at "/2"
175 if (prescalerIndex
< 0 || prescalerIndex
>= (int)ARRAYLEN(baudRatePrescaler
)) {
179 spi
->hspi
.Init
.BaudRatePrescaler
= baudRatePrescaler
[prescalerIndex
];
181 HAL_SPI_Init(&spi
->hspi
);
185 DMA_HandleTypeDef
* dmaHandleByInstance(SPI_TypeDef
*instance
)
187 return &spiDevice
[spiDeviceByInstance(instance
)].hdma
;
190 void SPI1_IRQHandler(void)
192 HAL_SPI_IRQHandler(&spiDevice
[SPIDEV_1
].hspi
);
195 void SPI2_IRQHandler(void)
197 HAL_SPI_IRQHandler(&spiDevice
[SPIDEV_2
].hspi
);
200 void SPI3_IRQHandler(void)
202 HAL_SPI_IRQHandler(&spiDevice
[SPIDEV_3
].hspi
);
205 void SPI4_IRQHandler(void)
207 HAL_SPI_IRQHandler(&spiDevice
[SPIDEV_4
].hspi
);
210 void dmaSPIIRQHandler(dmaChannelDescriptor_t
* descriptor
)
212 SPIDevice device
= descriptor
->userParam
;
213 if (device
!= SPIINVALID
)
214 HAL_DMA_IRQHandler(&spiDevice
[device
].hdma
);