mbed SDK library sources

Fork of mbed-src by mbed official

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:
Wed Sep 25 10:30:04 2013 +0100
Revision:
30:91c1d09ada54
Child:
32:4742f6c694e8
Synchronized with git revision 8f57c1e84759991fa81ede0da2b4aabe8530fa09

Who changed what in which revision?

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