Modification of Mbed-dev library for LQFP48 package microcontrollers: STM32F103C8 (STM32F103C8T6) and STM32F103CB (STM32F103CBT6) (Bluepill boards, Maple mini etc. )

Fork of mbed-STM32F103C8_org by Nothing Special

Library for STM32F103C8 (Bluepill boards etc.).
Use this instead of mbed library.
This library allows the size of the code in the FLASH up to 128kB. Therefore, code also runs on microcontrollers STM32F103CB (eg. Maple mini).
But in the case of STM32F103C8, check the size of the resulting code would not exceed 64kB.

To compile a program with this library, use NUCLEO-F103RB as the target name. !

Changes:

  • Corrected initialization of the HSE + crystal clock (mbed permanent bug), allowing the use of on-board xtal (8MHz).(1)
  • Additionally, it also set USB clock (48Mhz).(2)
  • Definitions of pins and peripherals adjusted to LQFP48 case.
  • Board led LED1 is now PC_13 (3)
  • USER_BUTTON is now PC_14 (4)

    Now the library is complete rebuilt based on mbed-dev v160 (and not yet fully tested).

notes
(1) - In case 8MHz xtal on board, CPU frequency is 72MHz. Without xtal is 64MHz.
(2) - Using the USB interface is only possible if STM32 is clocking by on-board 8MHz xtal or external clock signal 8MHz on the OSC_IN pin.
(3) - On Bluepill board led operation is reversed, i.e. 0 - led on, 1 - led off.
(4) - Bluepill board has no real user button

Information

After export to SW4STM (AC6):

  • add line #include "mbed_config.h" in files Serial.h and RawSerial.h
  • in project properties change Optimisation Level to Optimise for size (-Os)
Committer:
mega64
Date:
Thu Apr 27 23:56:38 2017 +0000
Revision:
148:8b0b02bf146f
Parent:
146:03e976389d16
Remove unnecessary folders

Who changed what in which revision?

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