mbed library sources

Dependents:   Encrypted my_mbed lklk CyaSSL_DTLS_Cellular ... more

Superseded

This library was superseded by mbed-dev - https://os.mbed.com/users/mbed_official/code/mbed-dev/.

Development branch of the mbed library sources. This library is kept in synch with the latest changes from the mbed SDK and it is not guaranteed to work.

If you are looking for a stable and tested release, please import one of the official mbed library releases:

Import librarymbed

The official Mbed 2 C/C++ SDK provides the software platform and libraries to build your applications.

Committer:
mbed_official
Date:
Fri Sep 11 09:30:09 2015 +0100
Revision:
621:9c82b0f79f3d
Parent:
552:a1b9575155a3
Synchronized with git revision 6c1d63e069ab9bd86de92e8296ca783681257538

Full URL: https://github.com/mbedmicro/mbed/commit/6c1d63e069ab9bd86de92e8296ca783681257538/

ignore target files not supported by the yotta module

Who changed what in which revision?

UserRevisionLine numberNew contents of line
bogdanm 20:4263a77256ae 1 /* mbed Microcontroller Library
bogdanm 20:4263a77256ae 2 * Copyright (c) 2006-2013 ARM Limited
bogdanm 20:4263a77256ae 3 *
bogdanm 20:4263a77256ae 4 * Licensed under the Apache License, Version 2.0 (the "License");
bogdanm 20:4263a77256ae 5 * you may not use this file except in compliance with the License.
bogdanm 20:4263a77256ae 6 * You may obtain a copy of the License at
bogdanm 20:4263a77256ae 7 *
bogdanm 20:4263a77256ae 8 * http://www.apache.org/licenses/LICENSE-2.0
bogdanm 20:4263a77256ae 9 *
bogdanm 20:4263a77256ae 10 * Unless required by applicable law or agreed to in writing, software
bogdanm 20:4263a77256ae 11 * distributed under the License is distributed on an "AS IS" BASIS,
bogdanm 20:4263a77256ae 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
bogdanm 20:4263a77256ae 13 * See the License for the specific language governing permissions and
bogdanm 20:4263a77256ae 14 * limitations under the License.
bogdanm 20:4263a77256ae 15 */
mbed_official 227:7bd0639b8911 16 #include "mbed_assert.h"
bogdanm 20:4263a77256ae 17 #include "spi_api.h"
bogdanm 20:4263a77256ae 18
bogdanm 20:4263a77256ae 19 #if DEVICE_SPI
bogdanm 20:4263a77256ae 20 #include <math.h>
bogdanm 20:4263a77256ae 21
bogdanm 20:4263a77256ae 22 #include "cmsis.h"
bogdanm 20:4263a77256ae 23 #include "pinmap.h"
bogdanm 20:4263a77256ae 24
bogdanm 20:4263a77256ae 25 static const PinMap PinMap_SPI_SCLK[] = {
bogdanm 20:4263a77256ae 26 {PA_5, SPI_1, STM_PIN_DATA(2, 5)},
bogdanm 20:4263a77256ae 27 {PB_3, SPI_1, STM_PIN_DATA(2, 5)},
bogdanm 20:4263a77256ae 28 {PB_3, SPI_3, STM_PIN_DATA(2, 6)},
bogdanm 20:4263a77256ae 29 {PB_10, SPI_2, STM_PIN_DATA(2, 5)},
bogdanm 20:4263a77256ae 30 {PB_13, SPI_2, STM_PIN_DATA(2, 5)},
bogdanm 20:4263a77256ae 31 {PC_10, SPI_3, STM_PIN_DATA(2, 6)},
bogdanm 20:4263a77256ae 32 {NC, NC, 0}
bogdanm 20:4263a77256ae 33 };
bogdanm 20:4263a77256ae 34
bogdanm 20:4263a77256ae 35 static const PinMap PinMap_SPI_MOSI[] = {
bogdanm 20:4263a77256ae 36 {PA_7, SPI_1, STM_PIN_DATA(2, 5)},
bogdanm 20:4263a77256ae 37 {PB_5, SPI_1, STM_PIN_DATA(2, 5)},
bogdanm 20:4263a77256ae 38 {PB_5, SPI_3, STM_PIN_DATA(2, 6)},
bogdanm 20:4263a77256ae 39 {PB_15, SPI_2, STM_PIN_DATA(2, 5)},
bogdanm 20:4263a77256ae 40 {PC_3, SPI_2, STM_PIN_DATA(2, 5)},
bogdanm 20:4263a77256ae 41 {PC_12, SPI_3, STM_PIN_DATA(2, 6)},
bogdanm 20:4263a77256ae 42 {NC, NC, 0}
bogdanm 20:4263a77256ae 43 };
bogdanm 20:4263a77256ae 44
bogdanm 20:4263a77256ae 45 static const PinMap PinMap_SPI_MISO[] = {
bogdanm 20:4263a77256ae 46 {PA_6, SPI_1, STM_PIN_DATA(2, 5)},
bogdanm 20:4263a77256ae 47 {PB_4, SPI_1, STM_PIN_DATA(2, 5)},
bogdanm 20:4263a77256ae 48 {PB_4, SPI_3, STM_PIN_DATA(2, 6)},
bogdanm 20:4263a77256ae 49 {PB_14, SPI_2, STM_PIN_DATA(2, 5)},
bogdanm 20:4263a77256ae 50 {PC_2, SPI_2, STM_PIN_DATA(2, 5)},
bogdanm 20:4263a77256ae 51 {PC_11, SPI_3, STM_PIN_DATA(2, 6)},
bogdanm 20:4263a77256ae 52 {NC, NC, 0}
bogdanm 20:4263a77256ae 53 };
bogdanm 20:4263a77256ae 54
bogdanm 20:4263a77256ae 55 static const PinMap PinMap_SPI_SSEL[] = {
bogdanm 20:4263a77256ae 56 {PA_4, SPI_1, STM_PIN_DATA(2, 5)},
bogdanm 20:4263a77256ae 57 {PA_4, SPI_3, STM_PIN_DATA(2, 6)},
bogdanm 20:4263a77256ae 58 {PA_15, SPI_1, STM_PIN_DATA(2, 5)},
bogdanm 20:4263a77256ae 59 {PA_15, SPI_3, STM_PIN_DATA(2, 6)},
mbed_official 227:7bd0639b8911 60 {PB_9, SPI_2, STM_PIN_DATA(2, 5)},
bogdanm 20:4263a77256ae 61 {PB_12, SPI_2, STM_PIN_DATA(2, 5)},
bogdanm 20:4263a77256ae 62 {NC, NC, 0}
bogdanm 20:4263a77256ae 63 };
bogdanm 20:4263a77256ae 64
bogdanm 20:4263a77256ae 65
bogdanm 20:4263a77256ae 66 static inline int ssp_disable(spi_t *obj);
bogdanm 20:4263a77256ae 67 static inline int ssp_enable(spi_t *obj);
bogdanm 20:4263a77256ae 68
bogdanm 20:4263a77256ae 69 void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel) {
bogdanm 20:4263a77256ae 70 // determine the SPI to use
bogdanm 20:4263a77256ae 71 SPIName spi_mosi = (SPIName)pinmap_peripheral(mosi, PinMap_SPI_MOSI);
bogdanm 20:4263a77256ae 72 SPIName spi_miso = (SPIName)pinmap_peripheral(miso, PinMap_SPI_MISO);
bogdanm 20:4263a77256ae 73 SPIName spi_sclk = (SPIName)pinmap_peripheral(sclk, PinMap_SPI_SCLK);
bogdanm 20:4263a77256ae 74 SPIName spi_ssel = (SPIName)pinmap_peripheral(ssel, PinMap_SPI_SSEL);
bogdanm 20:4263a77256ae 75 SPIName spi_data = (SPIName)pinmap_merge(spi_mosi, spi_miso);
bogdanm 20:4263a77256ae 76 SPIName spi_cntl = (SPIName)pinmap_merge(spi_sclk, spi_ssel);
bogdanm 20:4263a77256ae 77 obj->spi = (SPI_TypeDef*)pinmap_merge(spi_data, spi_cntl);
mbed_official 271:ccdf646660f2 78 MBED_ASSERT((int)obj->spi != NC);
bogdanm 20:4263a77256ae 79
bogdanm 20:4263a77256ae 80 // enable power and clocking
bogdanm 20:4263a77256ae 81 switch ((int)obj->spi) {
bogdanm 20:4263a77256ae 82 case SPI_1:
bogdanm 20:4263a77256ae 83 RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN | RCC_AHB1ENR_GPIOBEN;
bogdanm 20:4263a77256ae 84 RCC->APB2ENR |= RCC_APB2ENR_SPI1EN;
bogdanm 20:4263a77256ae 85 break;
bogdanm 20:4263a77256ae 86 case SPI_2:
bogdanm 20:4263a77256ae 87 RCC->AHB1ENR |= RCC_AHB1ENR_GPIOBEN | RCC_AHB1ENR_GPIOCEN;
bogdanm 20:4263a77256ae 88 RCC->APB1ENR |= RCC_APB1ENR_SPI2EN;
bogdanm 20:4263a77256ae 89 break;
bogdanm 20:4263a77256ae 90 case SPI_3:
bogdanm 20:4263a77256ae 91 RCC->AHB1ENR |= RCC_AHB1ENR_GPIOBEN | RCC_AHB1ENR_GPIOCEN;
bogdanm 20:4263a77256ae 92 RCC->APB1ENR |= RCC_APB1ENR_SPI3EN;
bogdanm 20:4263a77256ae 93 break;
bogdanm 20:4263a77256ae 94 }
bogdanm 20:4263a77256ae 95
bogdanm 20:4263a77256ae 96 // pin out the spi pins
bogdanm 20:4263a77256ae 97 pinmap_pinout(mosi, PinMap_SPI_MOSI);
bogdanm 20:4263a77256ae 98 pinmap_pinout(miso, PinMap_SPI_MISO);
bogdanm 20:4263a77256ae 99 pinmap_pinout(sclk, PinMap_SPI_SCLK);
bogdanm 20:4263a77256ae 100 if (ssel != NC) {
bogdanm 20:4263a77256ae 101 pinmap_pinout(ssel, PinMap_SPI_SSEL);
mbed_official 552:a1b9575155a3 102 } else {
bogdanm 20:4263a77256ae 103 // Use software slave management
bogdanm 20:4263a77256ae 104 obj->spi->CR1 |= SPI_CR1_SSM | SPI_CR1_SSI;
bogdanm 20:4263a77256ae 105 }
bogdanm 20:4263a77256ae 106 }
bogdanm 20:4263a77256ae 107
bogdanm 20:4263a77256ae 108 void spi_free(spi_t *obj) {}
bogdanm 20:4263a77256ae 109
bogdanm 20:4263a77256ae 110 void spi_format(spi_t *obj, int bits, int mode, int slave) {
mbed_official 227:7bd0639b8911 111 MBED_ASSERT(((bits == 8) || (bits == 16)) && ((mode >= 0) && (mode <= 3)));
bogdanm 20:4263a77256ae 112 ssp_disable(obj);
bogdanm 20:4263a77256ae 113
bogdanm 20:4263a77256ae 114 int polarity = (mode & 0x2) ? 1 : 0;
bogdanm 20:4263a77256ae 115 int phase = (mode & 0x1) ? 1 : 0;
bogdanm 20:4263a77256ae 116
bogdanm 20:4263a77256ae 117 obj->spi->CR1 &= ~0x807;
bogdanm 20:4263a77256ae 118 obj->spi->CR1 |= ((phase) ? 1 : 0) << 0 |
bogdanm 20:4263a77256ae 119 ((polarity) ? 1 : 0) << 1 |
bogdanm 20:4263a77256ae 120 ((slave) ? 0: 1) << 2 |
bogdanm 20:4263a77256ae 121 ((bits == 16) ? 1 : 0) << 11;
bogdanm 20:4263a77256ae 122
mbed_official 552:a1b9575155a3 123 if (slave) {
mbed_official 552:a1b9575155a3 124 // Use software slave management
mbed_official 552:a1b9575155a3 125 obj->spi->CR1 |= SPI_CR1_SSM | SPI_CR1_SSI;
mbed_official 552:a1b9575155a3 126 }
mbed_official 552:a1b9575155a3 127
bogdanm 20:4263a77256ae 128 if (obj->spi->SR & SPI_SR_MODF) {
bogdanm 20:4263a77256ae 129 obj->spi->CR1 = obj->spi->CR1;
bogdanm 20:4263a77256ae 130 }
bogdanm 20:4263a77256ae 131
bogdanm 20:4263a77256ae 132 ssp_enable(obj);
bogdanm 20:4263a77256ae 133 }
bogdanm 20:4263a77256ae 134
bogdanm 20:4263a77256ae 135 void spi_frequency(spi_t *obj, int hz) {
bogdanm 20:4263a77256ae 136 ssp_disable(obj);
bogdanm 20:4263a77256ae 137
bogdanm 20:4263a77256ae 138 // SPI1 runs from PCLK2, which runs at SystemCoreClock / 2. SPI2 and SPI3
bogdanm 20:4263a77256ae 139 // run from PCLK1, which runs at SystemCoreClock / 4.
bogdanm 20:4263a77256ae 140 uint32_t PCLK = SystemCoreClock;
bogdanm 20:4263a77256ae 141 switch ((int)obj->spi) {
bogdanm 20:4263a77256ae 142 case SPI_1: PCLK = PCLK >> 1; break;
bogdanm 20:4263a77256ae 143 case SPI_2: PCLK = PCLK >> 2; break;
bogdanm 20:4263a77256ae 144 case SPI_3: PCLK = PCLK >> 2; break;
bogdanm 20:4263a77256ae 145 }
bogdanm 20:4263a77256ae 146
bogdanm 20:4263a77256ae 147 // Choose the baud rate divisor (between 2 and 256)
bogdanm 20:4263a77256ae 148 uint32_t divisor = PCLK / hz;
bogdanm 20:4263a77256ae 149
bogdanm 20:4263a77256ae 150 // Find the nearest power-of-2
bogdanm 20:4263a77256ae 151 divisor = divisor > 0 ? divisor-1 : 0;
bogdanm 20:4263a77256ae 152 divisor |= divisor >> 1;
bogdanm 20:4263a77256ae 153 divisor |= divisor >> 2;
bogdanm 20:4263a77256ae 154 divisor |= divisor >> 4;
bogdanm 20:4263a77256ae 155 divisor |= divisor >> 8;
bogdanm 20:4263a77256ae 156 divisor |= divisor >> 16;
bogdanm 20:4263a77256ae 157 divisor++;
bogdanm 20:4263a77256ae 158
bogdanm 20:4263a77256ae 159 uint32_t baud_rate = __builtin_ffs(divisor) - 1;
bogdanm 20:4263a77256ae 160 baud_rate = baud_rate > 0x7 ? 0x7 : baud_rate;
bogdanm 20:4263a77256ae 161
bogdanm 20:4263a77256ae 162 obj->spi->CR1 &= ~(0x7 << 3);
bogdanm 20:4263a77256ae 163 obj->spi->CR1 |= baud_rate << 3;
bogdanm 20:4263a77256ae 164
bogdanm 20:4263a77256ae 165 ssp_enable(obj);
bogdanm 20:4263a77256ae 166 }
bogdanm 20:4263a77256ae 167
bogdanm 20:4263a77256ae 168 static inline int ssp_disable(spi_t *obj) {
bogdanm 20:4263a77256ae 169 // TODO: Follow the instructions in 25.3.8 for safely disabling the SPI
bogdanm 20:4263a77256ae 170 return obj->spi->CR1 &= ~SPI_CR1_SPE;
bogdanm 20:4263a77256ae 171 }
bogdanm 20:4263a77256ae 172
bogdanm 20:4263a77256ae 173 static inline int ssp_enable(spi_t *obj) {
bogdanm 20:4263a77256ae 174 return obj->spi->CR1 |= SPI_CR1_SPE;
bogdanm 20:4263a77256ae 175 }
bogdanm 20:4263a77256ae 176
bogdanm 20:4263a77256ae 177 static inline int ssp_readable(spi_t *obj) {
bogdanm 20:4263a77256ae 178 return obj->spi->SR & SPI_SR_RXNE;
bogdanm 20:4263a77256ae 179 }
bogdanm 20:4263a77256ae 180
bogdanm 20:4263a77256ae 181 static inline int ssp_writeable(spi_t *obj) {
bogdanm 20:4263a77256ae 182 return obj->spi->SR & SPI_SR_TXE;
bogdanm 20:4263a77256ae 183 }
bogdanm 20:4263a77256ae 184
bogdanm 20:4263a77256ae 185 static inline void ssp_write(spi_t *obj, int value) {
bogdanm 20:4263a77256ae 186 while (!ssp_writeable(obj));
bogdanm 20:4263a77256ae 187 obj->spi->DR = value;
bogdanm 20:4263a77256ae 188 }
bogdanm 20:4263a77256ae 189
bogdanm 20:4263a77256ae 190 static inline int ssp_read(spi_t *obj) {
bogdanm 20:4263a77256ae 191 while (!ssp_readable(obj));
bogdanm 20:4263a77256ae 192 return obj->spi->DR;
bogdanm 20:4263a77256ae 193 }
bogdanm 20:4263a77256ae 194
bogdanm 20:4263a77256ae 195 static inline int ssp_busy(spi_t *obj) {
bogdanm 20:4263a77256ae 196 return (obj->spi->SR & SPI_SR_BSY) ? (1) : (0);
bogdanm 20:4263a77256ae 197 }
bogdanm 20:4263a77256ae 198
bogdanm 20:4263a77256ae 199 int spi_master_write(spi_t *obj, int value) {
bogdanm 20:4263a77256ae 200 ssp_write(obj, value);
bogdanm 20:4263a77256ae 201 return ssp_read(obj);
bogdanm 20:4263a77256ae 202 }
bogdanm 20:4263a77256ae 203
bogdanm 20:4263a77256ae 204 int spi_slave_receive(spi_t *obj) {
bogdanm 20:4263a77256ae 205 return (ssp_readable(obj) && !ssp_busy(obj)) ? (1) : (0);
bogdanm 20:4263a77256ae 206 };
bogdanm 20:4263a77256ae 207
bogdanm 20:4263a77256ae 208 int spi_slave_read(spi_t *obj) {
bogdanm 20:4263a77256ae 209 return obj->spi->DR;
bogdanm 20:4263a77256ae 210 }
bogdanm 20:4263a77256ae 211
bogdanm 20:4263a77256ae 212 void spi_slave_write(spi_t *obj, int value) {
bogdanm 20:4263a77256ae 213 while (ssp_writeable(obj) == 0) ;
bogdanm 20:4263a77256ae 214 obj->spi->DR = value;
bogdanm 20:4263a77256ae 215 }
bogdanm 20:4263a77256ae 216
bogdanm 20:4263a77256ae 217 int spi_busy(spi_t *obj) {
bogdanm 20:4263a77256ae 218 return ssp_busy(obj);
bogdanm 20:4263a77256ae 219 }
bogdanm 20:4263a77256ae 220
bogdanm 20:4263a77256ae 221 #endif