From Ben Katz mbed-dev library. Removed unnecessary target files to reduce the overall size by a factor of 10 to make it easier to import into the online IDE.

Dependents:   motor_driver motor_driver_screaming_fix

Committer:
saloutos
Date:
Thu Nov 26 04:08:56 2020 +0000
Revision:
0:083111ae2a11
first commit of leaned mbed dev lib

Who changed what in which revision?

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