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:
Mon Aug 19 18:17:02 2013 +0300
Revision:
19:398f4c622e1b
Sync with official mbed library release 66

Who changed what in which revision?

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