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:
bogdanm
Date:
Wed Aug 07 16:43:59 2013 +0300
Revision:
15:4892fe388435
Child:
81:a9456fdf72fa
Added LPC4088 target and interrupt chaining code

Who changed what in which revision?

UserRevisionLine numberNew contents of line
bogdanm 15:4892fe388435 1 /* mbed Microcontroller Library
bogdanm 15:4892fe388435 2 * Copyright (c) 2006-2013 ARM Limited
bogdanm 15:4892fe388435 3 *
bogdanm 15:4892fe388435 4 * Licensed under the Apache License, Version 2.0 (the "License");
bogdanm 15:4892fe388435 5 * you may not use this file except in compliance with the License.
bogdanm 15:4892fe388435 6 * You may obtain a copy of the License at
bogdanm 15:4892fe388435 7 *
bogdanm 15:4892fe388435 8 * http://www.apache.org/licenses/LICENSE-2.0
bogdanm 15:4892fe388435 9 *
bogdanm 15:4892fe388435 10 * Unless required by applicable law or agreed to in writing, software
bogdanm 15:4892fe388435 11 * distributed under the License is distributed on an "AS IS" BASIS,
bogdanm 15:4892fe388435 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
bogdanm 15:4892fe388435 13 * See the License for the specific language governing permissions and
bogdanm 15:4892fe388435 14 * limitations under the License.
bogdanm 15:4892fe388435 15 */
bogdanm 15:4892fe388435 16 #include <math.h>
bogdanm 15:4892fe388435 17
bogdanm 15:4892fe388435 18 #include "spi_api.h"
bogdanm 15:4892fe388435 19 #include "cmsis.h"
bogdanm 15:4892fe388435 20 #include "pinmap.h"
bogdanm 15:4892fe388435 21 #include "error.h"
bogdanm 15:4892fe388435 22
bogdanm 15:4892fe388435 23 static const PinMap PinMap_SPI_SCLK[] = {
bogdanm 15:4892fe388435 24 {P0_7 , SPI_1, 2},
bogdanm 15:4892fe388435 25 {P0_15, SPI_0, 2},
bogdanm 15:4892fe388435 26 {P1_0, SPI_2, 4},
bogdanm 15:4892fe388435 27 {P1_19, SPI_1, 5},
bogdanm 15:4892fe388435 28 {P1_20, SPI_0, 5},
bogdanm 15:4892fe388435 29 {P1_31, SPI_1, 2},
bogdanm 15:4892fe388435 30 {P2_22, SPI_0, 2},
bogdanm 15:4892fe388435 31 {P4_20, SPI_1, 3},
bogdanm 15:4892fe388435 32 {P5_2, SPI_2, 2},
bogdanm 15:4892fe388435 33 {NC , NC , 0}
bogdanm 15:4892fe388435 34 };
bogdanm 15:4892fe388435 35
bogdanm 15:4892fe388435 36 static const PinMap PinMap_SPI_MOSI[] = {
bogdanm 15:4892fe388435 37 {P0_9 , SPI_1, 2},
bogdanm 15:4892fe388435 38 {P0_13, SPI_1, 2},
bogdanm 15:4892fe388435 39 {P0_18, SPI_0, 2},
bogdanm 15:4892fe388435 40 {P1_1, SPI_2, 4},
bogdanm 15:4892fe388435 41 {P1_22, SPI_1, 5},
bogdanm 15:4892fe388435 42 {P1_24, SPI_0, 5},
bogdanm 15:4892fe388435 43 {P2_27, SPI_0, 2},
bogdanm 15:4892fe388435 44 {P4_23, SPI_1, 3},
bogdanm 15:4892fe388435 45 {P5_0, SPI_2, 2},
bogdanm 15:4892fe388435 46 {NC , NC , 0}
bogdanm 15:4892fe388435 47 };
bogdanm 15:4892fe388435 48
bogdanm 15:4892fe388435 49 static const PinMap PinMap_SPI_MISO[] = {
bogdanm 15:4892fe388435 50 {P0_8 , SPI_1, 2},
bogdanm 15:4892fe388435 51 {P0_12, SPI_1, 2},
bogdanm 15:4892fe388435 52 {P0_17, SPI_0, 2},
bogdanm 15:4892fe388435 53 {P1_4, SPI_2, 4},
bogdanm 15:4892fe388435 54 {P1_18, SPI_1, 5},
bogdanm 15:4892fe388435 55 {P1_23, SPI_0, 5},
bogdanm 15:4892fe388435 56 {P2_26, SPI_0, 2},
bogdanm 15:4892fe388435 57 {P4_22, SPI_1, 3},
bogdanm 15:4892fe388435 58 {P5_1, SPI_2, 2},
bogdanm 15:4892fe388435 59 {NC , NC , 0}
bogdanm 15:4892fe388435 60 };
bogdanm 15:4892fe388435 61
bogdanm 15:4892fe388435 62 static const PinMap PinMap_SPI_SSEL[] = {
bogdanm 15:4892fe388435 63 {P0_6 , SPI_1, 2},
bogdanm 15:4892fe388435 64 {P0_14, SPI_1, 2},
bogdanm 15:4892fe388435 65 {P0_16, SPI_0, 2},
bogdanm 15:4892fe388435 66 {P1_8, SPI_2, 4},
bogdanm 15:4892fe388435 67 {P1_21, SPI_0, 3},
bogdanm 15:4892fe388435 68 {P1_26, SPI_1, 5},
bogdanm 15:4892fe388435 69 {P1_28, SPI_0, 5},
bogdanm 15:4892fe388435 70 {P2_23, SPI_0, 2},
bogdanm 15:4892fe388435 71 {P4_21, SPI_1, 3},
bogdanm 15:4892fe388435 72 {NC , NC , 0}
bogdanm 15:4892fe388435 73 };
bogdanm 15:4892fe388435 74
bogdanm 15:4892fe388435 75 static inline int ssp_disable(spi_t *obj);
bogdanm 15:4892fe388435 76 static inline int ssp_enable(spi_t *obj);
bogdanm 15:4892fe388435 77
bogdanm 15:4892fe388435 78 void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel) {
bogdanm 15:4892fe388435 79 // determine the SPI to use
bogdanm 15:4892fe388435 80 SPIName spi_mosi = (SPIName)pinmap_peripheral(mosi, PinMap_SPI_MOSI);
bogdanm 15:4892fe388435 81 SPIName spi_miso = (SPIName)pinmap_peripheral(miso, PinMap_SPI_MISO);
bogdanm 15:4892fe388435 82 SPIName spi_sclk = (SPIName)pinmap_peripheral(sclk, PinMap_SPI_SCLK);
bogdanm 15:4892fe388435 83 SPIName spi_ssel = (SPIName)pinmap_peripheral(ssel, PinMap_SPI_SSEL);
bogdanm 15:4892fe388435 84 SPIName spi_data = (SPIName)pinmap_merge(spi_mosi, spi_miso);
bogdanm 15:4892fe388435 85 SPIName spi_cntl = (SPIName)pinmap_merge(spi_sclk, spi_ssel);
bogdanm 15:4892fe388435 86 obj->spi = (LPC_SSP_TypeDef*)pinmap_merge(spi_data, spi_cntl);
bogdanm 15:4892fe388435 87 if ((int)obj->spi == NC) {
bogdanm 15:4892fe388435 88 error("SPI pinout mapping failed");
bogdanm 15:4892fe388435 89 }
bogdanm 15:4892fe388435 90
bogdanm 15:4892fe388435 91 // enable power and clocking
bogdanm 15:4892fe388435 92 switch ((int)obj->spi) {
bogdanm 15:4892fe388435 93 case SPI_0: LPC_SC->PCONP |= 1 << 21; break;
bogdanm 15:4892fe388435 94 case SPI_1: LPC_SC->PCONP |= 1 << 10; break;
bogdanm 15:4892fe388435 95 case SPI_2: LPC_SC->PCONP |= 1 << 20; break;
bogdanm 15:4892fe388435 96 }
bogdanm 15:4892fe388435 97
bogdanm 15:4892fe388435 98 // set default format and frequency
bogdanm 15:4892fe388435 99 if (ssel == NC) {
bogdanm 15:4892fe388435 100 spi_format(obj, 8, 0, 0); // 8 bits, mode 0, master
bogdanm 15:4892fe388435 101 } else {
bogdanm 15:4892fe388435 102 spi_format(obj, 8, 0, 1); // 8 bits, mode 0, slave
bogdanm 15:4892fe388435 103 }
bogdanm 15:4892fe388435 104 spi_frequency(obj, 1000000);
bogdanm 15:4892fe388435 105
bogdanm 15:4892fe388435 106 // enable the ssp channel
bogdanm 15:4892fe388435 107 ssp_enable(obj);
bogdanm 15:4892fe388435 108
bogdanm 15:4892fe388435 109 // pin out the spi pins
bogdanm 15:4892fe388435 110 pinmap_pinout(mosi, PinMap_SPI_MOSI);
bogdanm 15:4892fe388435 111 pinmap_pinout(miso, PinMap_SPI_MISO);
bogdanm 15:4892fe388435 112 pinmap_pinout(sclk, PinMap_SPI_SCLK);
bogdanm 15:4892fe388435 113 if (ssel != NC) {
bogdanm 15:4892fe388435 114 pinmap_pinout(ssel, PinMap_SPI_SSEL);
bogdanm 15:4892fe388435 115 }
bogdanm 15:4892fe388435 116 }
bogdanm 15:4892fe388435 117
bogdanm 15:4892fe388435 118 void spi_free(spi_t *obj) {}
bogdanm 15:4892fe388435 119
bogdanm 15:4892fe388435 120 void spi_format(spi_t *obj, int bits, int mode, int slave) {
bogdanm 15:4892fe388435 121 ssp_disable(obj);
bogdanm 15:4892fe388435 122
bogdanm 15:4892fe388435 123 if (!(bits >= 4 && bits <= 16) || !(mode >= 0 && mode <= 3)) {
bogdanm 15:4892fe388435 124 error("SPI format error");
bogdanm 15:4892fe388435 125 }
bogdanm 15:4892fe388435 126
bogdanm 15:4892fe388435 127 int polarity = (mode & 0x2) ? 1 : 0;
bogdanm 15:4892fe388435 128 int phase = (mode & 0x1) ? 1 : 0;
bogdanm 15:4892fe388435 129
bogdanm 15:4892fe388435 130 // set it up
bogdanm 15:4892fe388435 131 int DSS = bits - 1; // DSS (data select size)
bogdanm 15:4892fe388435 132 int SPO = (polarity) ? 1 : 0; // SPO - clock out polarity
bogdanm 15:4892fe388435 133 int SPH = (phase) ? 1 : 0; // SPH - clock out phase
bogdanm 15:4892fe388435 134
bogdanm 15:4892fe388435 135 int FRF = 0; // FRF (frame format) = SPI
bogdanm 15:4892fe388435 136 uint32_t tmp = obj->spi->CR0;
bogdanm 15:4892fe388435 137 tmp &= ~(0xFFFF);
bogdanm 15:4892fe388435 138 tmp |= DSS << 0
bogdanm 15:4892fe388435 139 | FRF << 4
bogdanm 15:4892fe388435 140 | SPO << 6
bogdanm 15:4892fe388435 141 | SPH << 7;
bogdanm 15:4892fe388435 142 obj->spi->CR0 = tmp;
bogdanm 15:4892fe388435 143
bogdanm 15:4892fe388435 144 tmp = obj->spi->CR1;
bogdanm 15:4892fe388435 145 tmp &= ~(0xD);
bogdanm 15:4892fe388435 146 tmp |= 0 << 0 // LBM - loop back mode - off
bogdanm 15:4892fe388435 147 | ((slave) ? 1 : 0) << 2 // MS - master slave mode, 1 = slave
bogdanm 15:4892fe388435 148 | 0 << 3; // SOD - slave output disable - na
bogdanm 15:4892fe388435 149 obj->spi->CR1 = tmp;
bogdanm 15:4892fe388435 150 ssp_enable(obj);
bogdanm 15:4892fe388435 151 }
bogdanm 15:4892fe388435 152
bogdanm 15:4892fe388435 153 void spi_frequency(spi_t *obj, int hz) {
bogdanm 15:4892fe388435 154 ssp_disable(obj);
bogdanm 15:4892fe388435 155
bogdanm 15:4892fe388435 156 uint32_t PCLK = PeripheralClock;
bogdanm 15:4892fe388435 157
bogdanm 15:4892fe388435 158 int prescaler;
bogdanm 15:4892fe388435 159
bogdanm 15:4892fe388435 160 for (prescaler = 2; prescaler <= 254; prescaler += 2) {
bogdanm 15:4892fe388435 161 int prescale_hz = PCLK / prescaler;
bogdanm 15:4892fe388435 162
bogdanm 15:4892fe388435 163 // calculate the divider
bogdanm 15:4892fe388435 164 int divider = floor(((float)prescale_hz / (float)hz) + 0.5f);
bogdanm 15:4892fe388435 165
bogdanm 15:4892fe388435 166 // check we can support the divider
bogdanm 15:4892fe388435 167 if (divider < 256) {
bogdanm 15:4892fe388435 168 // prescaler
bogdanm 15:4892fe388435 169 obj->spi->CPSR = prescaler;
bogdanm 15:4892fe388435 170
bogdanm 15:4892fe388435 171 // divider
bogdanm 15:4892fe388435 172 obj->spi->CR0 &= ~(0xFFFF << 8);
bogdanm 15:4892fe388435 173 obj->spi->CR0 |= (divider - 1) << 8;
bogdanm 15:4892fe388435 174 ssp_enable(obj);
bogdanm 15:4892fe388435 175 return;
bogdanm 15:4892fe388435 176 }
bogdanm 15:4892fe388435 177 }
bogdanm 15:4892fe388435 178 error("Couldn't setup requested SPI frequency");
bogdanm 15:4892fe388435 179 }
bogdanm 15:4892fe388435 180
bogdanm 15:4892fe388435 181 static inline int ssp_disable(spi_t *obj) {
bogdanm 15:4892fe388435 182 return obj->spi->CR1 &= ~(1 << 1);
bogdanm 15:4892fe388435 183 }
bogdanm 15:4892fe388435 184
bogdanm 15:4892fe388435 185 static inline int ssp_enable(spi_t *obj) {
bogdanm 15:4892fe388435 186 return obj->spi->CR1 |= (1 << 1);
bogdanm 15:4892fe388435 187 }
bogdanm 15:4892fe388435 188
bogdanm 15:4892fe388435 189 static inline int ssp_readable(spi_t *obj) {
bogdanm 15:4892fe388435 190 return obj->spi->SR & (1 << 2);
bogdanm 15:4892fe388435 191 }
bogdanm 15:4892fe388435 192
bogdanm 15:4892fe388435 193 static inline int ssp_writeable(spi_t *obj) {
bogdanm 15:4892fe388435 194 return obj->spi->SR & (1 << 1);
bogdanm 15:4892fe388435 195 }
bogdanm 15:4892fe388435 196
bogdanm 15:4892fe388435 197 static inline void ssp_write(spi_t *obj, int value) {
bogdanm 15:4892fe388435 198 while (!ssp_writeable(obj));
bogdanm 15:4892fe388435 199 obj->spi->DR = value;
bogdanm 15:4892fe388435 200 }
bogdanm 15:4892fe388435 201
bogdanm 15:4892fe388435 202 static inline int ssp_read(spi_t *obj) {
bogdanm 15:4892fe388435 203 while (!ssp_readable(obj));
bogdanm 15:4892fe388435 204 return obj->spi->DR;
bogdanm 15:4892fe388435 205 }
bogdanm 15:4892fe388435 206
bogdanm 15:4892fe388435 207 static inline int ssp_busy(spi_t *obj) {
bogdanm 15:4892fe388435 208 return (obj->spi->SR & (1 << 4)) ? (1) : (0);
bogdanm 15:4892fe388435 209 }
bogdanm 15:4892fe388435 210
bogdanm 15:4892fe388435 211 int spi_master_write(spi_t *obj, int value) {
bogdanm 15:4892fe388435 212 ssp_write(obj, value);
bogdanm 15:4892fe388435 213 return ssp_read(obj);
bogdanm 15:4892fe388435 214 }
bogdanm 15:4892fe388435 215
bogdanm 15:4892fe388435 216 int spi_slave_receive(spi_t *obj) {
bogdanm 15:4892fe388435 217 return (ssp_readable(obj) && !ssp_busy(obj)) ? (1) : (0);
bogdanm 15:4892fe388435 218 };
bogdanm 15:4892fe388435 219
bogdanm 15:4892fe388435 220 int spi_slave_read(spi_t *obj) {
bogdanm 15:4892fe388435 221 return obj->spi->DR;
bogdanm 15:4892fe388435 222 }
bogdanm 15:4892fe388435 223
bogdanm 15:4892fe388435 224 void spi_slave_write(spi_t *obj, int value) {
bogdanm 15:4892fe388435 225 while (ssp_writeable(obj) == 0) ;
bogdanm 15:4892fe388435 226 obj->spi->DR = value;
bogdanm 15:4892fe388435 227 }
bogdanm 15:4892fe388435 228
bogdanm 15:4892fe388435 229 int spi_busy(spi_t *obj) {
bogdanm 15:4892fe388435 230 return ssp_busy(obj);
bogdanm 15:4892fe388435 231 }