Initial commit

Dependencies:   FastPWM

Committer:
lypinator
Date:
Wed Sep 16 01:11:49 2020 +0000
Revision:
0:bb348c97df44
Added PWM

Who changed what in which revision?

UserRevisionLine numberNew contents of line
lypinator 0:bb348c97df44 1 /* mbed Microcontroller Library
lypinator 0:bb348c97df44 2 *******************************************************************************
lypinator 0:bb348c97df44 3 * Copyright (c) 2015, STMicroelectronics
lypinator 0:bb348c97df44 4 * All rights reserved.
lypinator 0:bb348c97df44 5 *
lypinator 0:bb348c97df44 6 * Redistribution and use in source and binary forms, with or without
lypinator 0:bb348c97df44 7 * modification, are permitted provided that the following conditions are met:
lypinator 0:bb348c97df44 8 *
lypinator 0:bb348c97df44 9 * 1. Redistributions of source code must retain the above copyright notice,
lypinator 0:bb348c97df44 10 * this list of conditions and the following disclaimer.
lypinator 0:bb348c97df44 11 * 2. Redistributions in binary form must reproduce the above copyright notice,
lypinator 0:bb348c97df44 12 * this list of conditions and the following disclaimer in the documentation
lypinator 0:bb348c97df44 13 * and/or other materials provided with the distribution.
lypinator 0:bb348c97df44 14 * 3. Neither the name of STMicroelectronics nor the names of its contributors
lypinator 0:bb348c97df44 15 * may be used to endorse or promote products derived from this software
lypinator 0:bb348c97df44 16 * without specific prior written permission.
lypinator 0:bb348c97df44 17 *
lypinator 0:bb348c97df44 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
lypinator 0:bb348c97df44 19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
lypinator 0:bb348c97df44 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
lypinator 0:bb348c97df44 21 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
lypinator 0:bb348c97df44 22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
lypinator 0:bb348c97df44 23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
lypinator 0:bb348c97df44 24 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
lypinator 0:bb348c97df44 25 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
lypinator 0:bb348c97df44 26 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
lypinator 0:bb348c97df44 27 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
lypinator 0:bb348c97df44 28 *******************************************************************************
lypinator 0:bb348c97df44 29 */
lypinator 0:bb348c97df44 30 #include "mbed_assert.h"
lypinator 0:bb348c97df44 31 #include "mbed_error.h"
lypinator 0:bb348c97df44 32 #include "mbed_debug.h"
lypinator 0:bb348c97df44 33 #include "spi_api.h"
lypinator 0:bb348c97df44 34
lypinator 0:bb348c97df44 35 #if DEVICE_SPI
lypinator 0:bb348c97df44 36 #include <stdbool.h>
lypinator 0:bb348c97df44 37 #include <math.h>
lypinator 0:bb348c97df44 38 #include <string.h>
lypinator 0:bb348c97df44 39 #include "cmsis.h"
lypinator 0:bb348c97df44 40 #include "pinmap.h"
lypinator 0:bb348c97df44 41 #include "PeripheralPins.h"
lypinator 0:bb348c97df44 42 #include "spi_device.h"
lypinator 0:bb348c97df44 43
lypinator 0:bb348c97df44 44 #if DEVICE_SPI_ASYNCH
lypinator 0:bb348c97df44 45 #define SPI_INST(obj) ((SPI_TypeDef *)(obj->spi.spi))
lypinator 0:bb348c97df44 46 #else
lypinator 0:bb348c97df44 47 #define SPI_INST(obj) ((SPI_TypeDef *)(obj->spi))
lypinator 0:bb348c97df44 48 #endif
lypinator 0:bb348c97df44 49
lypinator 0:bb348c97df44 50 #if DEVICE_SPI_ASYNCH
lypinator 0:bb348c97df44 51 #define SPI_S(obj) (( struct spi_s *)(&(obj->spi)))
lypinator 0:bb348c97df44 52 #else
lypinator 0:bb348c97df44 53 #define SPI_S(obj) (( struct spi_s *)(obj))
lypinator 0:bb348c97df44 54 #endif
lypinator 0:bb348c97df44 55
lypinator 0:bb348c97df44 56 #ifndef DEBUG_STDIO
lypinator 0:bb348c97df44 57 # define DEBUG_STDIO 0
lypinator 0:bb348c97df44 58 #endif
lypinator 0:bb348c97df44 59
lypinator 0:bb348c97df44 60 #if DEBUG_STDIO
lypinator 0:bb348c97df44 61 # include <stdio.h>
lypinator 0:bb348c97df44 62 # define DEBUG_PRINTF(...) do { printf(__VA_ARGS__); } while(0)
lypinator 0:bb348c97df44 63 #else
lypinator 0:bb348c97df44 64 # define DEBUG_PRINTF(...) {}
lypinator 0:bb348c97df44 65 #endif
lypinator 0:bb348c97df44 66
lypinator 0:bb348c97df44 67 /* Consider 10ms as the default timeout for sending/receving 1 byte */
lypinator 0:bb348c97df44 68 #define TIMEOUT_1_BYTE 10
lypinator 0:bb348c97df44 69
lypinator 0:bb348c97df44 70 #if defined(SPI_FLAG_FRLVL) // STM32F0 STM32F3 STM32F7 STM32L4
lypinator 0:bb348c97df44 71 extern HAL_StatusTypeDef HAL_SPIEx_FlushRxFifo(SPI_HandleTypeDef *hspi);
lypinator 0:bb348c97df44 72 #endif
lypinator 0:bb348c97df44 73
lypinator 0:bb348c97df44 74 void init_spi(spi_t *obj)
lypinator 0:bb348c97df44 75 {
lypinator 0:bb348c97df44 76 struct spi_s *spiobj = SPI_S(obj);
lypinator 0:bb348c97df44 77 SPI_HandleTypeDef *handle = &(spiobj->handle);
lypinator 0:bb348c97df44 78
lypinator 0:bb348c97df44 79 __HAL_SPI_DISABLE(handle);
lypinator 0:bb348c97df44 80
lypinator 0:bb348c97df44 81 DEBUG_PRINTF("init_spi: instance=0x%8X\r\n", (int)handle->Instance);
lypinator 0:bb348c97df44 82 if (HAL_SPI_Init(handle) != HAL_OK) {
lypinator 0:bb348c97df44 83 error("Cannot initialize SPI");
lypinator 0:bb348c97df44 84 }
lypinator 0:bb348c97df44 85
lypinator 0:bb348c97df44 86 /* In case of standard 4 wires SPI,PI can be kept enabled all time
lypinator 0:bb348c97df44 87 * and SCK will only be generated during the write operations. But in case
lypinator 0:bb348c97df44 88 * of 3 wires, it should be only enabled during rd/wr unitary operations,
lypinator 0:bb348c97df44 89 * which is handled inside STM32 HAL layer.
lypinator 0:bb348c97df44 90 */
lypinator 0:bb348c97df44 91 if (handle->Init.Direction == SPI_DIRECTION_2LINES) {
lypinator 0:bb348c97df44 92 __HAL_SPI_ENABLE(handle);
lypinator 0:bb348c97df44 93 }
lypinator 0:bb348c97df44 94 }
lypinator 0:bb348c97df44 95
lypinator 0:bb348c97df44 96 void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel)
lypinator 0:bb348c97df44 97 {
lypinator 0:bb348c97df44 98 struct spi_s *spiobj = SPI_S(obj);
lypinator 0:bb348c97df44 99 SPI_HandleTypeDef *handle = &(spiobj->handle);
lypinator 0:bb348c97df44 100
lypinator 0:bb348c97df44 101 // Determine the SPI to use
lypinator 0:bb348c97df44 102 SPIName spi_mosi = (SPIName)pinmap_peripheral(mosi, PinMap_SPI_MOSI);
lypinator 0:bb348c97df44 103 SPIName spi_miso = (SPIName)pinmap_peripheral(miso, PinMap_SPI_MISO);
lypinator 0:bb348c97df44 104 SPIName spi_sclk = (SPIName)pinmap_peripheral(sclk, PinMap_SPI_SCLK);
lypinator 0:bb348c97df44 105 SPIName spi_ssel = (SPIName)pinmap_peripheral(ssel, PinMap_SPI_SSEL);
lypinator 0:bb348c97df44 106
lypinator 0:bb348c97df44 107 SPIName spi_data = (SPIName)pinmap_merge(spi_mosi, spi_miso);
lypinator 0:bb348c97df44 108 SPIName spi_cntl = (SPIName)pinmap_merge(spi_sclk, spi_ssel);
lypinator 0:bb348c97df44 109
lypinator 0:bb348c97df44 110 spiobj->spi = (SPIName)pinmap_merge(spi_data, spi_cntl);
lypinator 0:bb348c97df44 111 MBED_ASSERT(spiobj->spi != (SPIName)NC);
lypinator 0:bb348c97df44 112
lypinator 0:bb348c97df44 113 #if defined SPI1_BASE
lypinator 0:bb348c97df44 114 // Enable SPI clock
lypinator 0:bb348c97df44 115 if (spiobj->spi == SPI_1) {
lypinator 0:bb348c97df44 116 __HAL_RCC_SPI1_CLK_ENABLE();
lypinator 0:bb348c97df44 117 spiobj->spiIRQ = SPI1_IRQn;
lypinator 0:bb348c97df44 118 }
lypinator 0:bb348c97df44 119 #endif
lypinator 0:bb348c97df44 120
lypinator 0:bb348c97df44 121 #if defined SPI2_BASE
lypinator 0:bb348c97df44 122 if (spiobj->spi == SPI_2) {
lypinator 0:bb348c97df44 123 __HAL_RCC_SPI2_CLK_ENABLE();
lypinator 0:bb348c97df44 124 spiobj->spiIRQ = SPI2_IRQn;
lypinator 0:bb348c97df44 125 }
lypinator 0:bb348c97df44 126 #endif
lypinator 0:bb348c97df44 127
lypinator 0:bb348c97df44 128 #if defined SPI3_BASE
lypinator 0:bb348c97df44 129 if (spiobj->spi == SPI_3) {
lypinator 0:bb348c97df44 130 __HAL_RCC_SPI3_CLK_ENABLE();
lypinator 0:bb348c97df44 131 spiobj->spiIRQ = SPI3_IRQn;
lypinator 0:bb348c97df44 132 }
lypinator 0:bb348c97df44 133 #endif
lypinator 0:bb348c97df44 134
lypinator 0:bb348c97df44 135 #if defined SPI4_BASE
lypinator 0:bb348c97df44 136 if (spiobj->spi == SPI_4) {
lypinator 0:bb348c97df44 137 __HAL_RCC_SPI4_CLK_ENABLE();
lypinator 0:bb348c97df44 138 spiobj->spiIRQ = SPI4_IRQn;
lypinator 0:bb348c97df44 139 }
lypinator 0:bb348c97df44 140 #endif
lypinator 0:bb348c97df44 141
lypinator 0:bb348c97df44 142 #if defined SPI5_BASE
lypinator 0:bb348c97df44 143 if (spiobj->spi == SPI_5) {
lypinator 0:bb348c97df44 144 __HAL_RCC_SPI5_CLK_ENABLE();
lypinator 0:bb348c97df44 145 spiobj->spiIRQ = SPI5_IRQn;
lypinator 0:bb348c97df44 146 }
lypinator 0:bb348c97df44 147 #endif
lypinator 0:bb348c97df44 148
lypinator 0:bb348c97df44 149 #if defined SPI6_BASE
lypinator 0:bb348c97df44 150 if (spiobj->spi == SPI_6) {
lypinator 0:bb348c97df44 151 __HAL_RCC_SPI6_CLK_ENABLE();
lypinator 0:bb348c97df44 152 spiobj->spiIRQ = SPI6_IRQn;
lypinator 0:bb348c97df44 153 }
lypinator 0:bb348c97df44 154 #endif
lypinator 0:bb348c97df44 155
lypinator 0:bb348c97df44 156 // Configure the SPI pins
lypinator 0:bb348c97df44 157 pinmap_pinout(mosi, PinMap_SPI_MOSI);
lypinator 0:bb348c97df44 158 pinmap_pinout(miso, PinMap_SPI_MISO);
lypinator 0:bb348c97df44 159 pinmap_pinout(sclk, PinMap_SPI_SCLK);
lypinator 0:bb348c97df44 160 spiobj->pin_miso = miso;
lypinator 0:bb348c97df44 161 spiobj->pin_mosi = mosi;
lypinator 0:bb348c97df44 162 spiobj->pin_sclk = sclk;
lypinator 0:bb348c97df44 163 spiobj->pin_ssel = ssel;
lypinator 0:bb348c97df44 164 if (ssel != NC) {
lypinator 0:bb348c97df44 165 pinmap_pinout(ssel, PinMap_SPI_SSEL);
lypinator 0:bb348c97df44 166 handle->Init.NSS = SPI_NSS_HARD_OUTPUT;
lypinator 0:bb348c97df44 167 } else {
lypinator 0:bb348c97df44 168 handle->Init.NSS = SPI_NSS_SOFT;
lypinator 0:bb348c97df44 169 }
lypinator 0:bb348c97df44 170
lypinator 0:bb348c97df44 171 /* Fill default value */
lypinator 0:bb348c97df44 172 handle->Instance = SPI_INST(obj);
lypinator 0:bb348c97df44 173 handle->Init.Mode = SPI_MODE_MASTER;
lypinator 0:bb348c97df44 174 handle->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_256;
lypinator 0:bb348c97df44 175
lypinator 0:bb348c97df44 176 if (miso != NC) {
lypinator 0:bb348c97df44 177 handle->Init.Direction = SPI_DIRECTION_2LINES;
lypinator 0:bb348c97df44 178 } else {
lypinator 0:bb348c97df44 179 handle->Init.Direction = SPI_DIRECTION_1LINE;
lypinator 0:bb348c97df44 180 }
lypinator 0:bb348c97df44 181
lypinator 0:bb348c97df44 182 handle->Init.CLKPhase = SPI_PHASE_1EDGE;
lypinator 0:bb348c97df44 183 handle->Init.CLKPolarity = SPI_POLARITY_LOW;
lypinator 0:bb348c97df44 184 handle->Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
lypinator 0:bb348c97df44 185 handle->Init.CRCPolynomial = 7;
lypinator 0:bb348c97df44 186 handle->Init.DataSize = SPI_DATASIZE_8BIT;
lypinator 0:bb348c97df44 187 handle->Init.FirstBit = SPI_FIRSTBIT_MSB;
lypinator 0:bb348c97df44 188 handle->Init.TIMode = SPI_TIMODE_DISABLE;
lypinator 0:bb348c97df44 189
lypinator 0:bb348c97df44 190 init_spi(obj);
lypinator 0:bb348c97df44 191 }
lypinator 0:bb348c97df44 192
lypinator 0:bb348c97df44 193 void spi_free(spi_t *obj)
lypinator 0:bb348c97df44 194 {
lypinator 0:bb348c97df44 195 struct spi_s *spiobj = SPI_S(obj);
lypinator 0:bb348c97df44 196 SPI_HandleTypeDef *handle = &(spiobj->handle);
lypinator 0:bb348c97df44 197
lypinator 0:bb348c97df44 198 DEBUG_PRINTF("spi_free\r\n");
lypinator 0:bb348c97df44 199
lypinator 0:bb348c97df44 200 __HAL_SPI_DISABLE(handle);
lypinator 0:bb348c97df44 201 HAL_SPI_DeInit(handle);
lypinator 0:bb348c97df44 202
lypinator 0:bb348c97df44 203 #if defined SPI1_BASE
lypinator 0:bb348c97df44 204 // Reset SPI and disable clock
lypinator 0:bb348c97df44 205 if (spiobj->spi == SPI_1) {
lypinator 0:bb348c97df44 206 __HAL_RCC_SPI1_FORCE_RESET();
lypinator 0:bb348c97df44 207 __HAL_RCC_SPI1_RELEASE_RESET();
lypinator 0:bb348c97df44 208 __HAL_RCC_SPI1_CLK_DISABLE();
lypinator 0:bb348c97df44 209 }
lypinator 0:bb348c97df44 210 #endif
lypinator 0:bb348c97df44 211 #if defined SPI2_BASE
lypinator 0:bb348c97df44 212 if (spiobj->spi == SPI_2) {
lypinator 0:bb348c97df44 213 __HAL_RCC_SPI2_FORCE_RESET();
lypinator 0:bb348c97df44 214 __HAL_RCC_SPI2_RELEASE_RESET();
lypinator 0:bb348c97df44 215 __HAL_RCC_SPI2_CLK_DISABLE();
lypinator 0:bb348c97df44 216 }
lypinator 0:bb348c97df44 217 #endif
lypinator 0:bb348c97df44 218
lypinator 0:bb348c97df44 219 #if defined SPI3_BASE
lypinator 0:bb348c97df44 220 if (spiobj->spi == SPI_3) {
lypinator 0:bb348c97df44 221 __HAL_RCC_SPI3_FORCE_RESET();
lypinator 0:bb348c97df44 222 __HAL_RCC_SPI3_RELEASE_RESET();
lypinator 0:bb348c97df44 223 __HAL_RCC_SPI3_CLK_DISABLE();
lypinator 0:bb348c97df44 224 }
lypinator 0:bb348c97df44 225 #endif
lypinator 0:bb348c97df44 226
lypinator 0:bb348c97df44 227 #if defined SPI4_BASE
lypinator 0:bb348c97df44 228 if (spiobj->spi == SPI_4) {
lypinator 0:bb348c97df44 229 __HAL_RCC_SPI4_FORCE_RESET();
lypinator 0:bb348c97df44 230 __HAL_RCC_SPI4_RELEASE_RESET();
lypinator 0:bb348c97df44 231 __HAL_RCC_SPI4_CLK_DISABLE();
lypinator 0:bb348c97df44 232 }
lypinator 0:bb348c97df44 233 #endif
lypinator 0:bb348c97df44 234
lypinator 0:bb348c97df44 235 #if defined SPI5_BASE
lypinator 0:bb348c97df44 236 if (spiobj->spi == SPI_5) {
lypinator 0:bb348c97df44 237 __HAL_RCC_SPI5_FORCE_RESET();
lypinator 0:bb348c97df44 238 __HAL_RCC_SPI5_RELEASE_RESET();
lypinator 0:bb348c97df44 239 __HAL_RCC_SPI5_CLK_DISABLE();
lypinator 0:bb348c97df44 240 }
lypinator 0:bb348c97df44 241 #endif
lypinator 0:bb348c97df44 242
lypinator 0:bb348c97df44 243 #if defined SPI6_BASE
lypinator 0:bb348c97df44 244 if (spiobj->spi == SPI_6) {
lypinator 0:bb348c97df44 245 __HAL_RCC_SPI6_FORCE_RESET();
lypinator 0:bb348c97df44 246 __HAL_RCC_SPI6_RELEASE_RESET();
lypinator 0:bb348c97df44 247 __HAL_RCC_SPI6_CLK_DISABLE();
lypinator 0:bb348c97df44 248 }
lypinator 0:bb348c97df44 249 #endif
lypinator 0:bb348c97df44 250
lypinator 0:bb348c97df44 251 // Configure GPIOs
lypinator 0:bb348c97df44 252 pin_function(spiobj->pin_miso, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, 0));
lypinator 0:bb348c97df44 253 pin_function(spiobj->pin_mosi, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, 0));
lypinator 0:bb348c97df44 254 pin_function(spiobj->pin_sclk, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, 0));
lypinator 0:bb348c97df44 255 if (handle->Init.NSS != SPI_NSS_SOFT) {
lypinator 0:bb348c97df44 256 pin_function(spiobj->pin_ssel, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, 0));
lypinator 0:bb348c97df44 257 }
lypinator 0:bb348c97df44 258 }
lypinator 0:bb348c97df44 259
lypinator 0:bb348c97df44 260 void spi_format(spi_t *obj, int bits, int mode, int slave)
lypinator 0:bb348c97df44 261 {
lypinator 0:bb348c97df44 262 struct spi_s *spiobj = SPI_S(obj);
lypinator 0:bb348c97df44 263 SPI_HandleTypeDef *handle = &(spiobj->handle);
lypinator 0:bb348c97df44 264
lypinator 0:bb348c97df44 265 DEBUG_PRINTF("spi_format, bits:%d, mode:%d, slave?:%d\r\n", bits, mode, slave);
lypinator 0:bb348c97df44 266
lypinator 0:bb348c97df44 267 // Save new values
lypinator 0:bb348c97df44 268 handle->Init.DataSize = (bits == 16) ? SPI_DATASIZE_16BIT : SPI_DATASIZE_8BIT;
lypinator 0:bb348c97df44 269
lypinator 0:bb348c97df44 270 switch (mode) {
lypinator 0:bb348c97df44 271 case 0:
lypinator 0:bb348c97df44 272 handle->Init.CLKPolarity = SPI_POLARITY_LOW;
lypinator 0:bb348c97df44 273 handle->Init.CLKPhase = SPI_PHASE_1EDGE;
lypinator 0:bb348c97df44 274 break;
lypinator 0:bb348c97df44 275 case 1:
lypinator 0:bb348c97df44 276 handle->Init.CLKPolarity = SPI_POLARITY_LOW;
lypinator 0:bb348c97df44 277 handle->Init.CLKPhase = SPI_PHASE_2EDGE;
lypinator 0:bb348c97df44 278 break;
lypinator 0:bb348c97df44 279 case 2:
lypinator 0:bb348c97df44 280 handle->Init.CLKPolarity = SPI_POLARITY_HIGH;
lypinator 0:bb348c97df44 281 handle->Init.CLKPhase = SPI_PHASE_1EDGE;
lypinator 0:bb348c97df44 282 break;
lypinator 0:bb348c97df44 283 default:
lypinator 0:bb348c97df44 284 handle->Init.CLKPolarity = SPI_POLARITY_HIGH;
lypinator 0:bb348c97df44 285 handle->Init.CLKPhase = SPI_PHASE_2EDGE;
lypinator 0:bb348c97df44 286 break;
lypinator 0:bb348c97df44 287 }
lypinator 0:bb348c97df44 288
lypinator 0:bb348c97df44 289 if (handle->Init.NSS != SPI_NSS_SOFT) {
lypinator 0:bb348c97df44 290 handle->Init.NSS = (slave) ? SPI_NSS_HARD_INPUT : SPI_NSS_HARD_OUTPUT;
lypinator 0:bb348c97df44 291 }
lypinator 0:bb348c97df44 292
lypinator 0:bb348c97df44 293 handle->Init.Mode = (slave) ? SPI_MODE_SLAVE : SPI_MODE_MASTER;
lypinator 0:bb348c97df44 294
lypinator 0:bb348c97df44 295 if (slave && (handle->Init.Direction == SPI_DIRECTION_1LINE)) {
lypinator 0:bb348c97df44 296 /* SPI slave implemtation in MBED does not support the 3 wires SPI.
lypinator 0:bb348c97df44 297 * (e.g. when MISO is not connected). So we're forcing slave in
lypinator 0:bb348c97df44 298 * 2LINES mode. As MISO is not connected, slave will only read
lypinator 0:bb348c97df44 299 * from master, and cannot write to it. Inform user.
lypinator 0:bb348c97df44 300 */
lypinator 0:bb348c97df44 301 debug("3 wires SPI slave not supported - slave will only read\r\n");
lypinator 0:bb348c97df44 302 handle->Init.Direction = SPI_DIRECTION_2LINES;
lypinator 0:bb348c97df44 303 }
lypinator 0:bb348c97df44 304
lypinator 0:bb348c97df44 305 init_spi(obj);
lypinator 0:bb348c97df44 306 }
lypinator 0:bb348c97df44 307
lypinator 0:bb348c97df44 308 /*
lypinator 0:bb348c97df44 309 * Only the IP clock input is family dependant so it computed
lypinator 0:bb348c97df44 310 * separately in spi_get_clock_freq
lypinator 0:bb348c97df44 311 */
lypinator 0:bb348c97df44 312 extern int spi_get_clock_freq(spi_t *obj);
lypinator 0:bb348c97df44 313
lypinator 0:bb348c97df44 314 static const uint16_t baudrate_prescaler_table[] = {SPI_BAUDRATEPRESCALER_2,
lypinator 0:bb348c97df44 315 SPI_BAUDRATEPRESCALER_4,
lypinator 0:bb348c97df44 316 SPI_BAUDRATEPRESCALER_8,
lypinator 0:bb348c97df44 317 SPI_BAUDRATEPRESCALER_16,
lypinator 0:bb348c97df44 318 SPI_BAUDRATEPRESCALER_32,
lypinator 0:bb348c97df44 319 SPI_BAUDRATEPRESCALER_64,
lypinator 0:bb348c97df44 320 SPI_BAUDRATEPRESCALER_128,
lypinator 0:bb348c97df44 321 SPI_BAUDRATEPRESCALER_256
lypinator 0:bb348c97df44 322 };
lypinator 0:bb348c97df44 323
lypinator 0:bb348c97df44 324 void spi_frequency(spi_t *obj, int hz)
lypinator 0:bb348c97df44 325 {
lypinator 0:bb348c97df44 326 struct spi_s *spiobj = SPI_S(obj);
lypinator 0:bb348c97df44 327 int spi_hz = 0;
lypinator 0:bb348c97df44 328 uint8_t prescaler_rank = 0;
lypinator 0:bb348c97df44 329 uint8_t last_index = (sizeof(baudrate_prescaler_table) / sizeof(baudrate_prescaler_table[0])) - 1;
lypinator 0:bb348c97df44 330 SPI_HandleTypeDef *handle = &(spiobj->handle);
lypinator 0:bb348c97df44 331
lypinator 0:bb348c97df44 332 /* Calculate the spi clock for prescaler_rank 0: SPI_BAUDRATEPRESCALER_2 */
lypinator 0:bb348c97df44 333 spi_hz = spi_get_clock_freq(obj) / 2;
lypinator 0:bb348c97df44 334
lypinator 0:bb348c97df44 335 /* Define pre-scaler in order to get highest available frequency below requested frequency */
lypinator 0:bb348c97df44 336 while ((spi_hz > hz) && (prescaler_rank < last_index)) {
lypinator 0:bb348c97df44 337 spi_hz = spi_hz / 2;
lypinator 0:bb348c97df44 338 prescaler_rank++;
lypinator 0:bb348c97df44 339 }
lypinator 0:bb348c97df44 340
lypinator 0:bb348c97df44 341 /* Use the best fit pre-scaler */
lypinator 0:bb348c97df44 342 handle->Init.BaudRatePrescaler = baudrate_prescaler_table[prescaler_rank];
lypinator 0:bb348c97df44 343
lypinator 0:bb348c97df44 344 /* In case maximum pre-scaler still gives too high freq, raise an error */
lypinator 0:bb348c97df44 345 if (spi_hz > hz) {
lypinator 0:bb348c97df44 346 DEBUG_PRINTF("WARNING: lowest SPI freq (%d) higher than requested (%d)\r\n", spi_hz, hz);
lypinator 0:bb348c97df44 347 }
lypinator 0:bb348c97df44 348
lypinator 0:bb348c97df44 349 DEBUG_PRINTF("spi_frequency, request:%d, select:%d\r\n", hz, spi_hz);
lypinator 0:bb348c97df44 350
lypinator 0:bb348c97df44 351 init_spi(obj);
lypinator 0:bb348c97df44 352 }
lypinator 0:bb348c97df44 353
lypinator 0:bb348c97df44 354 static inline int ssp_readable(spi_t *obj)
lypinator 0:bb348c97df44 355 {
lypinator 0:bb348c97df44 356 int status;
lypinator 0:bb348c97df44 357 struct spi_s *spiobj = SPI_S(obj);
lypinator 0:bb348c97df44 358 SPI_HandleTypeDef *handle = &(spiobj->handle);
lypinator 0:bb348c97df44 359
lypinator 0:bb348c97df44 360 // Check if data is received
lypinator 0:bb348c97df44 361 status = ((__HAL_SPI_GET_FLAG(handle, SPI_FLAG_RXNE) != RESET) ? 1 : 0);
lypinator 0:bb348c97df44 362 return status;
lypinator 0:bb348c97df44 363 }
lypinator 0:bb348c97df44 364
lypinator 0:bb348c97df44 365 static inline int ssp_writeable(spi_t *obj)
lypinator 0:bb348c97df44 366 {
lypinator 0:bb348c97df44 367 int status;
lypinator 0:bb348c97df44 368 struct spi_s *spiobj = SPI_S(obj);
lypinator 0:bb348c97df44 369 SPI_HandleTypeDef *handle = &(spiobj->handle);
lypinator 0:bb348c97df44 370
lypinator 0:bb348c97df44 371 // Check if data is transmitted
lypinator 0:bb348c97df44 372 status = ((__HAL_SPI_GET_FLAG(handle, SPI_FLAG_TXE) != RESET) ? 1 : 0);
lypinator 0:bb348c97df44 373 return status;
lypinator 0:bb348c97df44 374 }
lypinator 0:bb348c97df44 375
lypinator 0:bb348c97df44 376 static inline int ssp_busy(spi_t *obj)
lypinator 0:bb348c97df44 377 {
lypinator 0:bb348c97df44 378 int status;
lypinator 0:bb348c97df44 379 struct spi_s *spiobj = SPI_S(obj);
lypinator 0:bb348c97df44 380 SPI_HandleTypeDef *handle = &(spiobj->handle);
lypinator 0:bb348c97df44 381 status = ((__HAL_SPI_GET_FLAG(handle, SPI_FLAG_BSY) != RESET) ? 1 : 0);
lypinator 0:bb348c97df44 382 return status;
lypinator 0:bb348c97df44 383 }
lypinator 0:bb348c97df44 384
lypinator 0:bb348c97df44 385 int spi_master_write(spi_t *obj, int value)
lypinator 0:bb348c97df44 386 {
lypinator 0:bb348c97df44 387 struct spi_s *spiobj = SPI_S(obj);
lypinator 0:bb348c97df44 388 SPI_HandleTypeDef *handle = &(spiobj->handle);
lypinator 0:bb348c97df44 389
lypinator 0:bb348c97df44 390 if (handle->Init.Direction == SPI_DIRECTION_1LINE) {
lypinator 0:bb348c97df44 391 return HAL_SPI_Transmit(handle, (uint8_t *)&value, 1, TIMEOUT_1_BYTE);
lypinator 0:bb348c97df44 392 }
lypinator 0:bb348c97df44 393
lypinator 0:bb348c97df44 394 #if defined(LL_SPI_RX_FIFO_TH_HALF)
lypinator 0:bb348c97df44 395 /* Configure the default data size */
lypinator 0:bb348c97df44 396 if (handle->Init.DataSize == SPI_DATASIZE_16BIT) {
lypinator 0:bb348c97df44 397 LL_SPI_SetRxFIFOThreshold(SPI_INST(obj), LL_SPI_RX_FIFO_TH_HALF);
lypinator 0:bb348c97df44 398 } else {
lypinator 0:bb348c97df44 399 LL_SPI_SetRxFIFOThreshold(SPI_INST(obj), LL_SPI_RX_FIFO_TH_QUARTER);
lypinator 0:bb348c97df44 400 }
lypinator 0:bb348c97df44 401 #endif
lypinator 0:bb348c97df44 402
lypinator 0:bb348c97df44 403 /* Here we're using LL which means direct registers access
lypinator 0:bb348c97df44 404 * There is no error management, so we may end up looping
lypinator 0:bb348c97df44 405 * infinitely here in case of faulty device for insatnce,
lypinator 0:bb348c97df44 406 * but this will increase performances significantly
lypinator 0:bb348c97df44 407 */
lypinator 0:bb348c97df44 408
lypinator 0:bb348c97df44 409 /* Wait TXE flag to transmit data */
lypinator 0:bb348c97df44 410 while (!LL_SPI_IsActiveFlag_TXE(SPI_INST(obj)));
lypinator 0:bb348c97df44 411
lypinator 0:bb348c97df44 412 if (handle->Init.DataSize == SPI_DATASIZE_16BIT) {
lypinator 0:bb348c97df44 413 LL_SPI_TransmitData16(SPI_INST(obj), value);
lypinator 0:bb348c97df44 414 } else {
lypinator 0:bb348c97df44 415 LL_SPI_TransmitData8(SPI_INST(obj), (uint8_t) value);
lypinator 0:bb348c97df44 416 }
lypinator 0:bb348c97df44 417
lypinator 0:bb348c97df44 418 /* Then wait RXE flag before reading */
lypinator 0:bb348c97df44 419 while (!LL_SPI_IsActiveFlag_RXNE(SPI_INST(obj)));
lypinator 0:bb348c97df44 420
lypinator 0:bb348c97df44 421 if (handle->Init.DataSize == SPI_DATASIZE_16BIT) {
lypinator 0:bb348c97df44 422 return LL_SPI_ReceiveData16(SPI_INST(obj));
lypinator 0:bb348c97df44 423 } else {
lypinator 0:bb348c97df44 424 return LL_SPI_ReceiveData8(SPI_INST(obj));
lypinator 0:bb348c97df44 425 }
lypinator 0:bb348c97df44 426 }
lypinator 0:bb348c97df44 427
lypinator 0:bb348c97df44 428 int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length,
lypinator 0:bb348c97df44 429 char *rx_buffer, int rx_length, char write_fill)
lypinator 0:bb348c97df44 430 {
lypinator 0:bb348c97df44 431 struct spi_s *spiobj = SPI_S(obj);
lypinator 0:bb348c97df44 432 SPI_HandleTypeDef *handle = &(spiobj->handle);
lypinator 0:bb348c97df44 433 int total = (tx_length > rx_length) ? tx_length : rx_length;
lypinator 0:bb348c97df44 434 int i = 0;
lypinator 0:bb348c97df44 435 if (handle->Init.Direction == SPI_DIRECTION_2LINES) {
lypinator 0:bb348c97df44 436 for (i = 0; i < total; i++) {
lypinator 0:bb348c97df44 437 char out = (i < tx_length) ? tx_buffer[i] : write_fill;
lypinator 0:bb348c97df44 438 char in = spi_master_write(obj, out);
lypinator 0:bb348c97df44 439 if (i < rx_length) {
lypinator 0:bb348c97df44 440 rx_buffer[i] = in;
lypinator 0:bb348c97df44 441 }
lypinator 0:bb348c97df44 442 }
lypinator 0:bb348c97df44 443 } else {
lypinator 0:bb348c97df44 444 /* In case of 1 WIRE only, first handle TX, then Rx */
lypinator 0:bb348c97df44 445 if (tx_length != 0) {
lypinator 0:bb348c97df44 446 if (HAL_OK != HAL_SPI_Transmit(handle, (uint8_t *)tx_buffer, tx_length, tx_length * TIMEOUT_1_BYTE)) {
lypinator 0:bb348c97df44 447 /* report an error */
lypinator 0:bb348c97df44 448 total = 0;
lypinator 0:bb348c97df44 449 }
lypinator 0:bb348c97df44 450 }
lypinator 0:bb348c97df44 451 if (rx_length != 0) {
lypinator 0:bb348c97df44 452 if (HAL_OK != HAL_SPI_Receive(handle, (uint8_t *)rx_buffer, rx_length, rx_length * TIMEOUT_1_BYTE)) {
lypinator 0:bb348c97df44 453 /* report an error */
lypinator 0:bb348c97df44 454 total = 0;
lypinator 0:bb348c97df44 455 }
lypinator 0:bb348c97df44 456 }
lypinator 0:bb348c97df44 457 }
lypinator 0:bb348c97df44 458
lypinator 0:bb348c97df44 459 return total;
lypinator 0:bb348c97df44 460 }
lypinator 0:bb348c97df44 461
lypinator 0:bb348c97df44 462 int spi_slave_receive(spi_t *obj)
lypinator 0:bb348c97df44 463 {
lypinator 0:bb348c97df44 464 return ((ssp_readable(obj) && !ssp_busy(obj)) ? 1 : 0);
lypinator 0:bb348c97df44 465 };
lypinator 0:bb348c97df44 466
lypinator 0:bb348c97df44 467 int spi_slave_read(spi_t *obj)
lypinator 0:bb348c97df44 468 {
lypinator 0:bb348c97df44 469 struct spi_s *spiobj = SPI_S(obj);
lypinator 0:bb348c97df44 470 SPI_HandleTypeDef *handle = &(spiobj->handle);
lypinator 0:bb348c97df44 471 while (!ssp_readable(obj));
lypinator 0:bb348c97df44 472 if (handle->Init.DataSize == SPI_DATASIZE_16BIT) {
lypinator 0:bb348c97df44 473 return LL_SPI_ReceiveData16(SPI_INST(obj));
lypinator 0:bb348c97df44 474 } else {
lypinator 0:bb348c97df44 475 return LL_SPI_ReceiveData8(SPI_INST(obj));
lypinator 0:bb348c97df44 476 }
lypinator 0:bb348c97df44 477 }
lypinator 0:bb348c97df44 478
lypinator 0:bb348c97df44 479 void spi_slave_write(spi_t *obj, int value)
lypinator 0:bb348c97df44 480 {
lypinator 0:bb348c97df44 481 SPI_TypeDef *spi = SPI_INST(obj);
lypinator 0:bb348c97df44 482 struct spi_s *spiobj = SPI_S(obj);
lypinator 0:bb348c97df44 483 SPI_HandleTypeDef *handle = &(spiobj->handle);
lypinator 0:bb348c97df44 484 while (!ssp_writeable(obj));
lypinator 0:bb348c97df44 485 if (handle->Init.DataSize == SPI_DATASIZE_8BIT) {
lypinator 0:bb348c97df44 486 // Force 8-bit access to the data register
lypinator 0:bb348c97df44 487 uint8_t *p_spi_dr = 0;
lypinator 0:bb348c97df44 488 p_spi_dr = (uint8_t *) & (spi->DR);
lypinator 0:bb348c97df44 489 *p_spi_dr = (uint8_t)value;
lypinator 0:bb348c97df44 490 } else { // SPI_DATASIZE_16BIT
lypinator 0:bb348c97df44 491 spi->DR = (uint16_t)value;
lypinator 0:bb348c97df44 492 }
lypinator 0:bb348c97df44 493 }
lypinator 0:bb348c97df44 494
lypinator 0:bb348c97df44 495 int spi_busy(spi_t *obj)
lypinator 0:bb348c97df44 496 {
lypinator 0:bb348c97df44 497 return ssp_busy(obj);
lypinator 0:bb348c97df44 498 }
lypinator 0:bb348c97df44 499
lypinator 0:bb348c97df44 500 #ifdef DEVICE_SPI_ASYNCH
lypinator 0:bb348c97df44 501 typedef enum {
lypinator 0:bb348c97df44 502 SPI_TRANSFER_TYPE_NONE = 0,
lypinator 0:bb348c97df44 503 SPI_TRANSFER_TYPE_TX = 1,
lypinator 0:bb348c97df44 504 SPI_TRANSFER_TYPE_RX = 2,
lypinator 0:bb348c97df44 505 SPI_TRANSFER_TYPE_TXRX = 3,
lypinator 0:bb348c97df44 506 } transfer_type_t;
lypinator 0:bb348c97df44 507
lypinator 0:bb348c97df44 508
lypinator 0:bb348c97df44 509 /// @returns the number of bytes transferred, or `0` if nothing transferred
lypinator 0:bb348c97df44 510 static int spi_master_start_asynch_transfer(spi_t *obj, transfer_type_t transfer_type, const void *tx, void *rx, size_t length)
lypinator 0:bb348c97df44 511 {
lypinator 0:bb348c97df44 512 struct spi_s *spiobj = SPI_S(obj);
lypinator 0:bb348c97df44 513 SPI_HandleTypeDef *handle = &(spiobj->handle);
lypinator 0:bb348c97df44 514 bool is16bit = (handle->Init.DataSize == SPI_DATASIZE_16BIT);
lypinator 0:bb348c97df44 515 // the HAL expects number of transfers instead of number of bytes
lypinator 0:bb348c97df44 516 // so for 16 bit transfer width the count needs to be halved
lypinator 0:bb348c97df44 517 size_t words;
lypinator 0:bb348c97df44 518
lypinator 0:bb348c97df44 519 DEBUG_PRINTF("SPI inst=0x%8X Start: %u, %u\r\n", (int)handle->Instance, transfer_type, length);
lypinator 0:bb348c97df44 520
lypinator 0:bb348c97df44 521 obj->spi.transfer_type = transfer_type;
lypinator 0:bb348c97df44 522
lypinator 0:bb348c97df44 523 if (is16bit) {
lypinator 0:bb348c97df44 524 words = length / 2;
lypinator 0:bb348c97df44 525 } else {
lypinator 0:bb348c97df44 526 words = length;
lypinator 0:bb348c97df44 527 }
lypinator 0:bb348c97df44 528
lypinator 0:bb348c97df44 529 // enable the interrupt
lypinator 0:bb348c97df44 530 IRQn_Type irq_n = spiobj->spiIRQ;
lypinator 0:bb348c97df44 531 NVIC_DisableIRQ(irq_n);
lypinator 0:bb348c97df44 532 NVIC_ClearPendingIRQ(irq_n);
lypinator 0:bb348c97df44 533 NVIC_SetPriority(irq_n, 1);
lypinator 0:bb348c97df44 534 NVIC_EnableIRQ(irq_n);
lypinator 0:bb348c97df44 535
lypinator 0:bb348c97df44 536 // flush FIFO
lypinator 0:bb348c97df44 537 #if defined(SPI_FLAG_FRLVL) // STM32F0 STM32F3 STM32F7 STM32L4
lypinator 0:bb348c97df44 538 HAL_SPIEx_FlushRxFifo(handle);
lypinator 0:bb348c97df44 539 #endif
lypinator 0:bb348c97df44 540
lypinator 0:bb348c97df44 541 // enable the right hal transfer
lypinator 0:bb348c97df44 542 int rc = 0;
lypinator 0:bb348c97df44 543 switch (transfer_type) {
lypinator 0:bb348c97df44 544 case SPI_TRANSFER_TYPE_TXRX:
lypinator 0:bb348c97df44 545 rc = HAL_SPI_TransmitReceive_IT(handle, (uint8_t *)tx, (uint8_t *)rx, words);
lypinator 0:bb348c97df44 546 break;
lypinator 0:bb348c97df44 547 case SPI_TRANSFER_TYPE_TX:
lypinator 0:bb348c97df44 548 rc = HAL_SPI_Transmit_IT(handle, (uint8_t *)tx, words);
lypinator 0:bb348c97df44 549 break;
lypinator 0:bb348c97df44 550 case SPI_TRANSFER_TYPE_RX:
lypinator 0:bb348c97df44 551 // the receive function also "transmits" the receive buffer so in order
lypinator 0:bb348c97df44 552 // to guarantee that 0xff is on the line, we explicitly memset it here
lypinator 0:bb348c97df44 553 memset(rx, SPI_FILL_WORD, length);
lypinator 0:bb348c97df44 554 rc = HAL_SPI_Receive_IT(handle, (uint8_t *)rx, words);
lypinator 0:bb348c97df44 555 break;
lypinator 0:bb348c97df44 556 default:
lypinator 0:bb348c97df44 557 length = 0;
lypinator 0:bb348c97df44 558 }
lypinator 0:bb348c97df44 559
lypinator 0:bb348c97df44 560 if (rc) {
lypinator 0:bb348c97df44 561 DEBUG_PRINTF("SPI: RC=%u\n", rc);
lypinator 0:bb348c97df44 562 length = 0;
lypinator 0:bb348c97df44 563 }
lypinator 0:bb348c97df44 564
lypinator 0:bb348c97df44 565 return length;
lypinator 0:bb348c97df44 566 }
lypinator 0:bb348c97df44 567
lypinator 0:bb348c97df44 568 // asynchronous API
lypinator 0:bb348c97df44 569 void spi_master_transfer(spi_t *obj, const void *tx, size_t tx_length, void *rx, size_t rx_length, uint8_t bit_width, uint32_t handler, uint32_t event, DMAUsage hint)
lypinator 0:bb348c97df44 570 {
lypinator 0:bb348c97df44 571 struct spi_s *spiobj = SPI_S(obj);
lypinator 0:bb348c97df44 572 SPI_HandleTypeDef *handle = &(spiobj->handle);
lypinator 0:bb348c97df44 573
lypinator 0:bb348c97df44 574 // TODO: DMA usage is currently ignored
lypinator 0:bb348c97df44 575 (void) hint;
lypinator 0:bb348c97df44 576
lypinator 0:bb348c97df44 577 // check which use-case we have
lypinator 0:bb348c97df44 578 bool use_tx = (tx != NULL && tx_length > 0);
lypinator 0:bb348c97df44 579 bool use_rx = (rx != NULL && rx_length > 0);
lypinator 0:bb348c97df44 580 bool is16bit = (handle->Init.DataSize == SPI_DATASIZE_16BIT);
lypinator 0:bb348c97df44 581
lypinator 0:bb348c97df44 582 // don't do anything, if the buffers aren't valid
lypinator 0:bb348c97df44 583 if (!use_tx && !use_rx) {
lypinator 0:bb348c97df44 584 return;
lypinator 0:bb348c97df44 585 }
lypinator 0:bb348c97df44 586
lypinator 0:bb348c97df44 587 // copy the buffers to the SPI object
lypinator 0:bb348c97df44 588 obj->tx_buff.buffer = (void *) tx;
lypinator 0:bb348c97df44 589 obj->tx_buff.length = tx_length;
lypinator 0:bb348c97df44 590 obj->tx_buff.pos = 0;
lypinator 0:bb348c97df44 591 obj->tx_buff.width = is16bit ? 16 : 8;
lypinator 0:bb348c97df44 592
lypinator 0:bb348c97df44 593 obj->rx_buff.buffer = rx;
lypinator 0:bb348c97df44 594 obj->rx_buff.length = rx_length;
lypinator 0:bb348c97df44 595 obj->rx_buff.pos = 0;
lypinator 0:bb348c97df44 596 obj->rx_buff.width = obj->tx_buff.width;
lypinator 0:bb348c97df44 597
lypinator 0:bb348c97df44 598 obj->spi.event = event;
lypinator 0:bb348c97df44 599
lypinator 0:bb348c97df44 600 DEBUG_PRINTF("SPI: Transfer: %u, %u\n", tx_length, rx_length);
lypinator 0:bb348c97df44 601
lypinator 0:bb348c97df44 602 // register the thunking handler
lypinator 0:bb348c97df44 603 IRQn_Type irq_n = spiobj->spiIRQ;
lypinator 0:bb348c97df44 604 NVIC_SetVector(irq_n, (uint32_t)handler);
lypinator 0:bb348c97df44 605
lypinator 0:bb348c97df44 606 // enable the right hal transfer
lypinator 0:bb348c97df44 607 if (use_tx && use_rx) {
lypinator 0:bb348c97df44 608 // we cannot manage different rx / tx sizes, let's use smaller one
lypinator 0:bb348c97df44 609 size_t size = (tx_length < rx_length) ? tx_length : rx_length;
lypinator 0:bb348c97df44 610 if (tx_length != rx_length) {
lypinator 0:bb348c97df44 611 DEBUG_PRINTF("SPI: Full duplex transfer only 1 size: %d\n", size);
lypinator 0:bb348c97df44 612 obj->tx_buff.length = size;
lypinator 0:bb348c97df44 613 obj->rx_buff.length = size;
lypinator 0:bb348c97df44 614 }
lypinator 0:bb348c97df44 615 spi_master_start_asynch_transfer(obj, SPI_TRANSFER_TYPE_TXRX, tx, rx, size);
lypinator 0:bb348c97df44 616 } else if (use_tx) {
lypinator 0:bb348c97df44 617 spi_master_start_asynch_transfer(obj, SPI_TRANSFER_TYPE_TX, tx, NULL, tx_length);
lypinator 0:bb348c97df44 618 } else if (use_rx) {
lypinator 0:bb348c97df44 619 spi_master_start_asynch_transfer(obj, SPI_TRANSFER_TYPE_RX, NULL, rx, rx_length);
lypinator 0:bb348c97df44 620 }
lypinator 0:bb348c97df44 621 }
lypinator 0:bb348c97df44 622
lypinator 0:bb348c97df44 623 inline uint32_t spi_irq_handler_asynch(spi_t *obj)
lypinator 0:bb348c97df44 624 {
lypinator 0:bb348c97df44 625 int event = 0;
lypinator 0:bb348c97df44 626
lypinator 0:bb348c97df44 627 // call the CubeF4 handler, this will update the handle
lypinator 0:bb348c97df44 628 HAL_SPI_IRQHandler(&obj->spi.handle);
lypinator 0:bb348c97df44 629
lypinator 0:bb348c97df44 630 if (obj->spi.handle.State == HAL_SPI_STATE_READY) {
lypinator 0:bb348c97df44 631 // When HAL SPI is back to READY state, check if there was an error
lypinator 0:bb348c97df44 632 int error = obj->spi.handle.ErrorCode;
lypinator 0:bb348c97df44 633 if (error != HAL_SPI_ERROR_NONE) {
lypinator 0:bb348c97df44 634 // something went wrong and the transfer has definitely completed
lypinator 0:bb348c97df44 635 event = SPI_EVENT_ERROR | SPI_EVENT_INTERNAL_TRANSFER_COMPLETE;
lypinator 0:bb348c97df44 636
lypinator 0:bb348c97df44 637 if (error & HAL_SPI_ERROR_OVR) {
lypinator 0:bb348c97df44 638 // buffer overrun
lypinator 0:bb348c97df44 639 event |= SPI_EVENT_RX_OVERFLOW;
lypinator 0:bb348c97df44 640 }
lypinator 0:bb348c97df44 641 } else {
lypinator 0:bb348c97df44 642 // else we're done
lypinator 0:bb348c97df44 643 event = SPI_EVENT_COMPLETE | SPI_EVENT_INTERNAL_TRANSFER_COMPLETE;
lypinator 0:bb348c97df44 644 }
lypinator 0:bb348c97df44 645 // enable the interrupt
lypinator 0:bb348c97df44 646 NVIC_DisableIRQ(obj->spi.spiIRQ);
lypinator 0:bb348c97df44 647 NVIC_ClearPendingIRQ(obj->spi.spiIRQ);
lypinator 0:bb348c97df44 648 }
lypinator 0:bb348c97df44 649
lypinator 0:bb348c97df44 650
lypinator 0:bb348c97df44 651 return (event & (obj->spi.event | SPI_EVENT_INTERNAL_TRANSFER_COMPLETE));
lypinator 0:bb348c97df44 652 }
lypinator 0:bb348c97df44 653
lypinator 0:bb348c97df44 654 uint8_t spi_active(spi_t *obj)
lypinator 0:bb348c97df44 655 {
lypinator 0:bb348c97df44 656 struct spi_s *spiobj = SPI_S(obj);
lypinator 0:bb348c97df44 657 SPI_HandleTypeDef *handle = &(spiobj->handle);
lypinator 0:bb348c97df44 658 HAL_SPI_StateTypeDef state = HAL_SPI_GetState(handle);
lypinator 0:bb348c97df44 659
lypinator 0:bb348c97df44 660 switch (state) {
lypinator 0:bb348c97df44 661 case HAL_SPI_STATE_RESET:
lypinator 0:bb348c97df44 662 case HAL_SPI_STATE_READY:
lypinator 0:bb348c97df44 663 case HAL_SPI_STATE_ERROR:
lypinator 0:bb348c97df44 664 return 0;
lypinator 0:bb348c97df44 665 default:
lypinator 0:bb348c97df44 666 return 1;
lypinator 0:bb348c97df44 667 }
lypinator 0:bb348c97df44 668 }
lypinator 0:bb348c97df44 669
lypinator 0:bb348c97df44 670 void spi_abort_asynch(spi_t *obj)
lypinator 0:bb348c97df44 671 {
lypinator 0:bb348c97df44 672 struct spi_s *spiobj = SPI_S(obj);
lypinator 0:bb348c97df44 673 SPI_HandleTypeDef *handle = &(spiobj->handle);
lypinator 0:bb348c97df44 674
lypinator 0:bb348c97df44 675 // disable interrupt
lypinator 0:bb348c97df44 676 IRQn_Type irq_n = spiobj->spiIRQ;
lypinator 0:bb348c97df44 677 NVIC_ClearPendingIRQ(irq_n);
lypinator 0:bb348c97df44 678 NVIC_DisableIRQ(irq_n);
lypinator 0:bb348c97df44 679
lypinator 0:bb348c97df44 680 // clean-up
lypinator 0:bb348c97df44 681 __HAL_SPI_DISABLE(handle);
lypinator 0:bb348c97df44 682 HAL_SPI_DeInit(handle);
lypinator 0:bb348c97df44 683 HAL_SPI_Init(handle);
lypinator 0:bb348c97df44 684 __HAL_SPI_ENABLE(handle);
lypinator 0:bb348c97df44 685 }
lypinator 0:bb348c97df44 686
lypinator 0:bb348c97df44 687 #endif //DEVICE_SPI_ASYNCH
lypinator 0:bb348c97df44 688
lypinator 0:bb348c97df44 689 #endif