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:
Tue Jul 29 19:00:07 2014 +0100
Revision:
268:402bcc0c870b
Parent:
227:7bd0639b8911
Child:
271:ccdf646660f2
Synchronized with git revision 490d1a6606b3138f165c5edf2f2370ca616587c0

Full URL: https://github.com/mbedmicro/mbed/commit/490d1a6606b3138f165c5edf2f2370ca616587c0/

[LPC1114] Sleep fix + some device.h settings

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 227:7bd0639b8911 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
bogdanm 20:4263a77256ae 97 // set default format and frequency
bogdanm 20:4263a77256ae 98 if (ssel == NC) {
bogdanm 20:4263a77256ae 99 spi_format(obj, 8, 0, 0); // 8 bits, mode 0, master
bogdanm 20:4263a77256ae 100 } else {
bogdanm 20:4263a77256ae 101 spi_format(obj, 8, 0, 1); // 8 bits, mode 0, slave
bogdanm 20:4263a77256ae 102 }
bogdanm 20:4263a77256ae 103 spi_frequency(obj, 1000000);
bogdanm 20:4263a77256ae 104
bogdanm 20:4263a77256ae 105 // enable the ssp channel
bogdanm 20:4263a77256ae 106 ssp_enable(obj);
bogdanm 20:4263a77256ae 107
bogdanm 20:4263a77256ae 108 // pin out the spi pins
bogdanm 20:4263a77256ae 109 pinmap_pinout(mosi, PinMap_SPI_MOSI);
bogdanm 20:4263a77256ae 110 pinmap_pinout(miso, PinMap_SPI_MISO);
bogdanm 20:4263a77256ae 111 pinmap_pinout(sclk, PinMap_SPI_SCLK);
bogdanm 20:4263a77256ae 112 if (ssel != NC) {
bogdanm 20:4263a77256ae 113 pinmap_pinout(ssel, PinMap_SPI_SSEL);
bogdanm 20:4263a77256ae 114 }
bogdanm 20:4263a77256ae 115 else {
bogdanm 20:4263a77256ae 116 // Use software slave management
bogdanm 20:4263a77256ae 117 obj->spi->CR1 |= SPI_CR1_SSM | SPI_CR1_SSI;
bogdanm 20:4263a77256ae 118 }
bogdanm 20:4263a77256ae 119 }
bogdanm 20:4263a77256ae 120
bogdanm 20:4263a77256ae 121 void spi_free(spi_t *obj) {}
bogdanm 20:4263a77256ae 122
bogdanm 20:4263a77256ae 123 void spi_format(spi_t *obj, int bits, int mode, int slave) {
mbed_official 227:7bd0639b8911 124 MBED_ASSERT(((bits == 8) || (bits == 16)) && ((mode >= 0) && (mode <= 3)));
bogdanm 20:4263a77256ae 125 ssp_disable(obj);
bogdanm 20:4263a77256ae 126
bogdanm 20:4263a77256ae 127 int polarity = (mode & 0x2) ? 1 : 0;
bogdanm 20:4263a77256ae 128 int phase = (mode & 0x1) ? 1 : 0;
bogdanm 20:4263a77256ae 129
bogdanm 20:4263a77256ae 130 obj->spi->CR1 &= ~0x807;
bogdanm 20:4263a77256ae 131 obj->spi->CR1 |= ((phase) ? 1 : 0) << 0 |
bogdanm 20:4263a77256ae 132 ((polarity) ? 1 : 0) << 1 |
bogdanm 20:4263a77256ae 133 ((slave) ? 0: 1) << 2 |
bogdanm 20:4263a77256ae 134 ((bits == 16) ? 1 : 0) << 11;
bogdanm 20:4263a77256ae 135
bogdanm 20:4263a77256ae 136 if (obj->spi->SR & SPI_SR_MODF) {
bogdanm 20:4263a77256ae 137 obj->spi->CR1 = obj->spi->CR1;
bogdanm 20:4263a77256ae 138 }
bogdanm 20:4263a77256ae 139
bogdanm 20:4263a77256ae 140 ssp_enable(obj);
bogdanm 20:4263a77256ae 141 }
bogdanm 20:4263a77256ae 142
bogdanm 20:4263a77256ae 143 void spi_frequency(spi_t *obj, int hz) {
bogdanm 20:4263a77256ae 144 ssp_disable(obj);
bogdanm 20:4263a77256ae 145
bogdanm 20:4263a77256ae 146 // SPI1 runs from PCLK2, which runs at SystemCoreClock / 2. SPI2 and SPI3
bogdanm 20:4263a77256ae 147 // run from PCLK1, which runs at SystemCoreClock / 4.
bogdanm 20:4263a77256ae 148 uint32_t PCLK = SystemCoreClock;
bogdanm 20:4263a77256ae 149 switch ((int)obj->spi) {
bogdanm 20:4263a77256ae 150 case SPI_1: PCLK = PCLK >> 1; break;
bogdanm 20:4263a77256ae 151 case SPI_2: PCLK = PCLK >> 2; break;
bogdanm 20:4263a77256ae 152 case SPI_3: PCLK = PCLK >> 2; break;
bogdanm 20:4263a77256ae 153 }
bogdanm 20:4263a77256ae 154
bogdanm 20:4263a77256ae 155 // Choose the baud rate divisor (between 2 and 256)
bogdanm 20:4263a77256ae 156 uint32_t divisor = PCLK / hz;
bogdanm 20:4263a77256ae 157
bogdanm 20:4263a77256ae 158 // Find the nearest power-of-2
bogdanm 20:4263a77256ae 159 divisor = divisor > 0 ? divisor-1 : 0;
bogdanm 20:4263a77256ae 160 divisor |= divisor >> 1;
bogdanm 20:4263a77256ae 161 divisor |= divisor >> 2;
bogdanm 20:4263a77256ae 162 divisor |= divisor >> 4;
bogdanm 20:4263a77256ae 163 divisor |= divisor >> 8;
bogdanm 20:4263a77256ae 164 divisor |= divisor >> 16;
bogdanm 20:4263a77256ae 165 divisor++;
bogdanm 20:4263a77256ae 166
bogdanm 20:4263a77256ae 167 uint32_t baud_rate = __builtin_ffs(divisor) - 1;
bogdanm 20:4263a77256ae 168 baud_rate = baud_rate > 0x7 ? 0x7 : baud_rate;
bogdanm 20:4263a77256ae 169
bogdanm 20:4263a77256ae 170 obj->spi->CR1 &= ~(0x7 << 3);
bogdanm 20:4263a77256ae 171 obj->spi->CR1 |= baud_rate << 3;
bogdanm 20:4263a77256ae 172
bogdanm 20:4263a77256ae 173 ssp_enable(obj);
bogdanm 20:4263a77256ae 174 }
bogdanm 20:4263a77256ae 175
bogdanm 20:4263a77256ae 176 static inline int ssp_disable(spi_t *obj) {
bogdanm 20:4263a77256ae 177 // TODO: Follow the instructions in 25.3.8 for safely disabling the SPI
bogdanm 20:4263a77256ae 178 return obj->spi->CR1 &= ~SPI_CR1_SPE;
bogdanm 20:4263a77256ae 179 }
bogdanm 20:4263a77256ae 180
bogdanm 20:4263a77256ae 181 static inline int ssp_enable(spi_t *obj) {
bogdanm 20:4263a77256ae 182 return obj->spi->CR1 |= SPI_CR1_SPE;
bogdanm 20:4263a77256ae 183 }
bogdanm 20:4263a77256ae 184
bogdanm 20:4263a77256ae 185 static inline int ssp_readable(spi_t *obj) {
bogdanm 20:4263a77256ae 186 return obj->spi->SR & SPI_SR_RXNE;
bogdanm 20:4263a77256ae 187 }
bogdanm 20:4263a77256ae 188
bogdanm 20:4263a77256ae 189 static inline int ssp_writeable(spi_t *obj) {
bogdanm 20:4263a77256ae 190 return obj->spi->SR & SPI_SR_TXE;
bogdanm 20:4263a77256ae 191 }
bogdanm 20:4263a77256ae 192
bogdanm 20:4263a77256ae 193 static inline void ssp_write(spi_t *obj, int value) {
bogdanm 20:4263a77256ae 194 while (!ssp_writeable(obj));
bogdanm 20:4263a77256ae 195 obj->spi->DR = value;
bogdanm 20:4263a77256ae 196 }
bogdanm 20:4263a77256ae 197
bogdanm 20:4263a77256ae 198 static inline int ssp_read(spi_t *obj) {
bogdanm 20:4263a77256ae 199 while (!ssp_readable(obj));
bogdanm 20:4263a77256ae 200 return obj->spi->DR;
bogdanm 20:4263a77256ae 201 }
bogdanm 20:4263a77256ae 202
bogdanm 20:4263a77256ae 203 static inline int ssp_busy(spi_t *obj) {
bogdanm 20:4263a77256ae 204 return (obj->spi->SR & SPI_SR_BSY) ? (1) : (0);
bogdanm 20:4263a77256ae 205 }
bogdanm 20:4263a77256ae 206
bogdanm 20:4263a77256ae 207 int spi_master_write(spi_t *obj, int value) {
bogdanm 20:4263a77256ae 208 ssp_write(obj, value);
bogdanm 20:4263a77256ae 209 return ssp_read(obj);
bogdanm 20:4263a77256ae 210 }
bogdanm 20:4263a77256ae 211
bogdanm 20:4263a77256ae 212 int spi_slave_receive(spi_t *obj) {
bogdanm 20:4263a77256ae 213 return (ssp_readable(obj) && !ssp_busy(obj)) ? (1) : (0);
bogdanm 20:4263a77256ae 214 };
bogdanm 20:4263a77256ae 215
bogdanm 20:4263a77256ae 216 int spi_slave_read(spi_t *obj) {
bogdanm 20:4263a77256ae 217 return obj->spi->DR;
bogdanm 20:4263a77256ae 218 }
bogdanm 20:4263a77256ae 219
bogdanm 20:4263a77256ae 220 void spi_slave_write(spi_t *obj, int value) {
bogdanm 20:4263a77256ae 221 while (ssp_writeable(obj) == 0) ;
bogdanm 20:4263a77256ae 222 obj->spi->DR = value;
bogdanm 20:4263a77256ae 223 }
bogdanm 20:4263a77256ae 224
bogdanm 20:4263a77256ae 225 int spi_busy(spi_t *obj) {
bogdanm 20:4263a77256ae 226 return ssp_busy(obj);
bogdanm 20:4263a77256ae 227 }
bogdanm 20:4263a77256ae 228
bogdanm 20:4263a77256ae 229 #endif