mbed library sources. Supersedes mbed-src.

Dependents:   Nucleo_Hello_Encoder BLE_iBeaconScan AM1805_DEMO DISCO-F429ZI_ExportTemplate1 ... more

Committer:
<>
Date:
Fri Sep 30 18:07:01 2016 +0100
Revision:
148:21d94c44109e
Parent:
144:ef7eb2e8f9f7
This updates the lib to the mbed lib v127

Who changed what in which revision?

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