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:
Mon Feb 16 17:15:07 2015 +0000
Revision:
477:5831be29b0ad
Parent:
285:31249416b6f9
Child:
552:a1b9575155a3
Synchronized with git revision 31f66c22e576852a6ab1e3a99773976eedd0641b

Full URL: https://github.com/mbedmicro/mbed/commit/31f66c22e576852a6ab1e3a99773976eedd0641b/

Who changed what in which revision?

UserRevisionLine numberNew contents of line
mbed_official 103:9b881da47c92 1 /* mbed Microcontroller Library
mbed_official 103:9b881da47c92 2 * Copyright (c) 2006-2013 ARM Limited
mbed_official 103:9b881da47c92 3 *
mbed_official 103:9b881da47c92 4 * Licensed under the Apache License, Version 2.0 (the "License");
mbed_official 103:9b881da47c92 5 * you may not use this file except in compliance with the License.
mbed_official 103:9b881da47c92 6 * You may obtain a copy of the License at
mbed_official 103:9b881da47c92 7 *
mbed_official 103:9b881da47c92 8 * http://www.apache.org/licenses/LICENSE-2.0
mbed_official 103:9b881da47c92 9 *
mbed_official 103:9b881da47c92 10 * Unless required by applicable law or agreed to in writing, software
mbed_official 103:9b881da47c92 11 * distributed under the License is distributed on an "AS IS" BASIS,
mbed_official 103:9b881da47c92 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
mbed_official 103:9b881da47c92 13 * See the License for the specific language governing permissions and
mbed_official 103:9b881da47c92 14 * limitations under the License.
mbed_official 103:9b881da47c92 15 */
mbed_official 227:7bd0639b8911 16 #include "mbed_assert.h"
mbed_official 103:9b881da47c92 17 #include <math.h>
mbed_official 103:9b881da47c92 18
mbed_official 103:9b881da47c92 19 #include "spi_api.h"
mbed_official 103:9b881da47c92 20 #include "cmsis.h"
mbed_official 103:9b881da47c92 21 #include "pinmap.h"
mbed_official 285:31249416b6f9 22 #include "mbed_error.h"
mbed_official 103:9b881da47c92 23
mbed_official 103:9b881da47c92 24 static const SWM_Map SWM_SPI_SSEL[] = {
mbed_official 103:9b881da47c92 25 {4, 0},
mbed_official 103:9b881da47c92 26 {5, 24},
mbed_official 103:9b881da47c92 27 };
mbed_official 103:9b881da47c92 28
mbed_official 103:9b881da47c92 29 static const SWM_Map SWM_SPI_SCLK[] = {
mbed_official 103:9b881da47c92 30 {3, 8},
mbed_official 103:9b881da47c92 31 {5, 0},
mbed_official 103:9b881da47c92 32 };
mbed_official 103:9b881da47c92 33
mbed_official 103:9b881da47c92 34 static const SWM_Map SWM_SPI_MOSI[] = {
mbed_official 103:9b881da47c92 35 {3, 16},
mbed_official 103:9b881da47c92 36 {5, 8},
mbed_official 103:9b881da47c92 37 };
mbed_official 103:9b881da47c92 38
mbed_official 103:9b881da47c92 39 static const SWM_Map SWM_SPI_MISO[] = {
mbed_official 103:9b881da47c92 40 {3, 24},
mbed_official 103:9b881da47c92 41 {5, 16},
mbed_official 103:9b881da47c92 42 };
mbed_official 103:9b881da47c92 43
mbed_official 103:9b881da47c92 44 // bit flags for used SPIs
mbed_official 103:9b881da47c92 45 static unsigned char spi_used = 0;
mbed_official 266:69e8a32876bd 46 static int get_available_spi(PinName mosi, PinName miso, PinName sclk, PinName ssel)
mbed_official 261:ee1cf08b7bc7 47 {
mbed_official 266:69e8a32876bd 48 if (spi_used == 0) {
mbed_official 266:69e8a32876bd 49 return 0; // The first user
mbed_official 103:9b881da47c92 50 }
mbed_official 266:69e8a32876bd 51
mbed_official 266:69e8a32876bd 52 const SWM_Map *swm;
mbed_official 266:69e8a32876bd 53 uint32_t regVal;
mbed_official 266:69e8a32876bd 54
mbed_official 266:69e8a32876bd 55 // Investigate if same pins as the used SPI0/1 - to be able to reuse it
mbed_official 266:69e8a32876bd 56 for (int spi_n = 0; spi_n < 2; spi_n++) {
mbed_official 266:69e8a32876bd 57 if (spi_used & (1<<spi_n)) {
mbed_official 266:69e8a32876bd 58 if (sclk != NC) {
mbed_official 266:69e8a32876bd 59 swm = &SWM_SPI_SCLK[spi_n];
mbed_official 266:69e8a32876bd 60 regVal = LPC_SWM->PINASSIGN[swm->n] & (0xFF << swm->offset);
mbed_official 266:69e8a32876bd 61 if (regVal != (sclk << swm->offset)) {
mbed_official 266:69e8a32876bd 62 // Existing pin is not the same as the one we want
mbed_official 266:69e8a32876bd 63 continue;
mbed_official 266:69e8a32876bd 64 }
mbed_official 266:69e8a32876bd 65 }
mbed_official 266:69e8a32876bd 66
mbed_official 266:69e8a32876bd 67 if (mosi != NC) {
mbed_official 266:69e8a32876bd 68 swm = &SWM_SPI_MOSI[spi_n];
mbed_official 266:69e8a32876bd 69 regVal = LPC_SWM->PINASSIGN[swm->n] & (0xFF << swm->offset);
mbed_official 266:69e8a32876bd 70 if (regVal != (mosi << swm->offset)) {
mbed_official 266:69e8a32876bd 71 // Existing pin is not the same as the one we want
mbed_official 266:69e8a32876bd 72 continue;
mbed_official 266:69e8a32876bd 73 }
mbed_official 266:69e8a32876bd 74 }
mbed_official 266:69e8a32876bd 75
mbed_official 266:69e8a32876bd 76 if (miso != NC) {
mbed_official 266:69e8a32876bd 77 swm = &SWM_SPI_MISO[spi_n];
mbed_official 266:69e8a32876bd 78 regVal = LPC_SWM->PINASSIGN[swm->n] & (0xFF << swm->offset);
mbed_official 266:69e8a32876bd 79 if (regVal != (miso << swm->offset)) {
mbed_official 266:69e8a32876bd 80 // Existing pin is not the same as the one we want
mbed_official 266:69e8a32876bd 81 continue;
mbed_official 266:69e8a32876bd 82 }
mbed_official 266:69e8a32876bd 83 }
mbed_official 266:69e8a32876bd 84
mbed_official 266:69e8a32876bd 85 if (ssel != NC) {
mbed_official 266:69e8a32876bd 86 swm = &SWM_SPI_SSEL[spi_n];
mbed_official 266:69e8a32876bd 87 regVal = LPC_SWM->PINASSIGN[swm->n] & (0xFF << swm->offset);
mbed_official 266:69e8a32876bd 88 if (regVal != (ssel << swm->offset)) {
mbed_official 266:69e8a32876bd 89 // Existing pin is not the same as the one we want
mbed_official 266:69e8a32876bd 90 continue;
mbed_official 266:69e8a32876bd 91 }
mbed_official 266:69e8a32876bd 92 }
mbed_official 266:69e8a32876bd 93
mbed_official 266:69e8a32876bd 94 // The pins for the currently used SPIx are the same as the
mbed_official 266:69e8a32876bd 95 // ones we want so we will reuse it
mbed_official 266:69e8a32876bd 96 return spi_n;
mbed_official 266:69e8a32876bd 97 }
mbed_official 266:69e8a32876bd 98 }
mbed_official 266:69e8a32876bd 99
mbed_official 266:69e8a32876bd 100 // None of the existing SPIx pin setups match the pins we want
mbed_official 266:69e8a32876bd 101 // so the last hope is to select one unused SPIx
mbed_official 266:69e8a32876bd 102 if ((spi_used & 1) == 0) {
mbed_official 266:69e8a32876bd 103 return 0;
mbed_official 266:69e8a32876bd 104 } else if ((spi_used & 2) == 0) {
mbed_official 266:69e8a32876bd 105 return 1;
mbed_official 266:69e8a32876bd 106 }
mbed_official 266:69e8a32876bd 107
mbed_official 266:69e8a32876bd 108 // No matching setup and no free SPIx
mbed_official 103:9b881da47c92 109 return -1;
mbed_official 103:9b881da47c92 110 }
mbed_official 103:9b881da47c92 111
mbed_official 103:9b881da47c92 112 static inline void spi_disable(spi_t *obj);
mbed_official 103:9b881da47c92 113 static inline void spi_enable(spi_t *obj);
mbed_official 103:9b881da47c92 114
mbed_official 261:ee1cf08b7bc7 115 void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel)
mbed_official 261:ee1cf08b7bc7 116 {
mbed_official 266:69e8a32876bd 117 int spi_n = get_available_spi(mosi, miso, sclk, ssel);
mbed_official 103:9b881da47c92 118 if (spi_n == -1) {
mbed_official 103:9b881da47c92 119 error("No available SPI");
mbed_official 103:9b881da47c92 120 }
mbed_official 103:9b881da47c92 121
mbed_official 103:9b881da47c92 122 obj->spi_n = spi_n;
mbed_official 103:9b881da47c92 123 spi_used |= (1 << spi_n);
mbed_official 261:ee1cf08b7bc7 124
mbed_official 103:9b881da47c92 125 obj->spi = (spi_n) ? (LPC_SPI0_Type *)(LPC_SPI1_BASE) : (LPC_SPI0_Type *)(LPC_SPI0_BASE);
mbed_official 261:ee1cf08b7bc7 126
mbed_official 103:9b881da47c92 127 const SWM_Map *swm;
mbed_official 103:9b881da47c92 128 uint32_t regVal;
mbed_official 261:ee1cf08b7bc7 129
mbed_official 103:9b881da47c92 130 if (sclk != NC) {
mbed_official 103:9b881da47c92 131 swm = &SWM_SPI_SCLK[obj->spi_n];
mbed_official 103:9b881da47c92 132 regVal = LPC_SWM->PINASSIGN[swm->n] & ~(0xFF << swm->offset);
mbed_official 103:9b881da47c92 133 LPC_SWM->PINASSIGN[swm->n] = regVal | (sclk << swm->offset);
mbed_official 103:9b881da47c92 134 }
mbed_official 261:ee1cf08b7bc7 135
mbed_official 103:9b881da47c92 136 if (mosi != NC) {
mbed_official 103:9b881da47c92 137 swm = &SWM_SPI_MOSI[obj->spi_n];
mbed_official 103:9b881da47c92 138 regVal = LPC_SWM->PINASSIGN[swm->n] & ~(0xFF << swm->offset);
mbed_official 103:9b881da47c92 139 LPC_SWM->PINASSIGN[swm->n] = regVal | (mosi << swm->offset);
mbed_official 103:9b881da47c92 140 }
mbed_official 261:ee1cf08b7bc7 141
mbed_official 103:9b881da47c92 142 if (miso != NC) {
mbed_official 103:9b881da47c92 143 swm = &SWM_SPI_MISO[obj->spi_n];
mbed_official 103:9b881da47c92 144 regVal = LPC_SWM->PINASSIGN[swm->n] & ~(0xFF << swm->offset);
mbed_official 103:9b881da47c92 145 LPC_SWM->PINASSIGN[swm->n] = regVal | (miso << swm->offset);
mbed_official 103:9b881da47c92 146 }
mbed_official 103:9b881da47c92 147
mbed_official 103:9b881da47c92 148 if (ssel != NC) {
mbed_official 103:9b881da47c92 149 swm = &SWM_SPI_SSEL[obj->spi_n];
mbed_official 103:9b881da47c92 150 regVal = LPC_SWM->PINASSIGN[swm->n] & ~(0xFF << swm->offset);
mbed_official 103:9b881da47c92 151 LPC_SWM->PINASSIGN[swm->n] = regVal | (ssel << swm->offset);
mbed_official 103:9b881da47c92 152 }
mbed_official 103:9b881da47c92 153
mbed_official 103:9b881da47c92 154 // clear interrupts
mbed_official 103:9b881da47c92 155 obj->spi->INTENCLR = 0x3f;
mbed_official 103:9b881da47c92 156
mbed_official 261:ee1cf08b7bc7 157 // enable power and clocking
mbed_official 261:ee1cf08b7bc7 158 LPC_SYSCON->SYSAHBCLKCTRL1 |= (0x1 << (obj->spi_n + 9));
mbed_official 261:ee1cf08b7bc7 159 LPC_SYSCON->PRESETCTRL1 |= (0x1 << (obj->spi_n + 9));
mbed_official 261:ee1cf08b7bc7 160 LPC_SYSCON->PRESETCTRL1 &= ~(0x1 << (obj->spi_n + 9));
mbed_official 261:ee1cf08b7bc7 161
mbed_official 103:9b881da47c92 162 // set default format and frequency
mbed_official 103:9b881da47c92 163 if (ssel == NC) {
mbed_official 103:9b881da47c92 164 spi_format(obj, 8, 0, 0); // 8 bits, mode 0, master
mbed_official 103:9b881da47c92 165 } else {
mbed_official 103:9b881da47c92 166 spi_format(obj, 8, 0, 1); // 8 bits, mode 0, slave
mbed_official 103:9b881da47c92 167 }
mbed_official 103:9b881da47c92 168 spi_frequency(obj, 1000000);
mbed_official 261:ee1cf08b7bc7 169
mbed_official 103:9b881da47c92 170 // enable the spi channel
mbed_official 103:9b881da47c92 171 spi_enable(obj);
mbed_official 103:9b881da47c92 172 }
mbed_official 103:9b881da47c92 173
mbed_official 261:ee1cf08b7bc7 174 void spi_free(spi_t *obj)
mbed_official 261:ee1cf08b7bc7 175 {
mbed_official 261:ee1cf08b7bc7 176 }
mbed_official 103:9b881da47c92 177
mbed_official 261:ee1cf08b7bc7 178 void spi_format(spi_t *obj, int bits, int mode, int slave)
mbed_official 261:ee1cf08b7bc7 179 {
mbed_official 103:9b881da47c92 180 spi_disable(obj);
mbed_official 227:7bd0639b8911 181 MBED_ASSERT((bits >= 1 && bits <= 16) && (mode >= 0 && mode <= 3));
mbed_official 261:ee1cf08b7bc7 182
mbed_official 103:9b881da47c92 183 int polarity = (mode & 0x2) ? 1 : 0;
mbed_official 103:9b881da47c92 184 int phase = (mode & 0x1) ? 1 : 0;
mbed_official 261:ee1cf08b7bc7 185
mbed_official 103:9b881da47c92 186 // set it up
mbed_official 103:9b881da47c92 187 int LEN = bits - 1; // LEN - Data Length
mbed_official 103:9b881da47c92 188 int CPOL = (polarity) ? 1 : 0; // CPOL - Clock Polarity select
mbed_official 103:9b881da47c92 189 int CPHA = (phase) ? 1 : 0; // CPHA - Clock Phase select
mbed_official 261:ee1cf08b7bc7 190
mbed_official 103:9b881da47c92 191 uint32_t tmp = obj->spi->CFG;
mbed_official 103:9b881da47c92 192 tmp &= ~((1 << 5) | (1 << 4) | (1 << 2));
mbed_official 103:9b881da47c92 193 tmp |= (CPOL << 5) | (CPHA << 4) | ((slave ? 0 : 1) << 2);
mbed_official 103:9b881da47c92 194 obj->spi->CFG = tmp;
mbed_official 261:ee1cf08b7bc7 195
mbed_official 103:9b881da47c92 196 // select frame length
mbed_official 266:69e8a32876bd 197 tmp = obj->spi->TXCTL;
mbed_official 103:9b881da47c92 198 tmp &= ~(0xf << 24);
mbed_official 103:9b881da47c92 199 tmp |= (LEN << 24);
mbed_official 266:69e8a32876bd 200 obj->spi->TXCTL = tmp;
mbed_official 261:ee1cf08b7bc7 201
mbed_official 103:9b881da47c92 202 spi_enable(obj);
mbed_official 103:9b881da47c92 203 }
mbed_official 103:9b881da47c92 204
mbed_official 261:ee1cf08b7bc7 205 void spi_frequency(spi_t *obj, int hz)
mbed_official 261:ee1cf08b7bc7 206 {
mbed_official 103:9b881da47c92 207 spi_disable(obj);
mbed_official 261:ee1cf08b7bc7 208
mbed_official 261:ee1cf08b7bc7 209 // rise DIV value if it cannot be divided
mbed_official 261:ee1cf08b7bc7 210 obj->spi->DIV = (SystemCoreClock + (hz - 1))/hz - 1;
mbed_official 103:9b881da47c92 211 obj->spi->DLY = 0;
mbed_official 261:ee1cf08b7bc7 212
mbed_official 103:9b881da47c92 213 spi_enable(obj);
mbed_official 103:9b881da47c92 214 }
mbed_official 103:9b881da47c92 215
mbed_official 261:ee1cf08b7bc7 216 static inline void spi_disable(spi_t *obj)
mbed_official 261:ee1cf08b7bc7 217 {
mbed_official 103:9b881da47c92 218 obj->spi->CFG &= ~(1 << 0);
mbed_official 103:9b881da47c92 219 }
mbed_official 103:9b881da47c92 220
mbed_official 261:ee1cf08b7bc7 221 static inline void spi_enable(spi_t *obj)
mbed_official 261:ee1cf08b7bc7 222 {
mbed_official 103:9b881da47c92 223 obj->spi->CFG |= (1 << 0);
mbed_official 103:9b881da47c92 224 }
mbed_official 103:9b881da47c92 225
mbed_official 261:ee1cf08b7bc7 226 static inline int spi_readable(spi_t *obj)
mbed_official 261:ee1cf08b7bc7 227 {
mbed_official 103:9b881da47c92 228 return obj->spi->STAT & (1 << 0);
mbed_official 103:9b881da47c92 229 }
mbed_official 103:9b881da47c92 230
mbed_official 261:ee1cf08b7bc7 231 static inline int spi_writeable(spi_t *obj)
mbed_official 261:ee1cf08b7bc7 232 {
mbed_official 103:9b881da47c92 233 return obj->spi->STAT & (1 << 1);
mbed_official 103:9b881da47c92 234 }
mbed_official 103:9b881da47c92 235
mbed_official 261:ee1cf08b7bc7 236 static inline void spi_write(spi_t *obj, int value)
mbed_official 261:ee1cf08b7bc7 237 {
mbed_official 103:9b881da47c92 238 while (!spi_writeable(obj));
mbed_official 103:9b881da47c92 239 // end of transfer
mbed_official 266:69e8a32876bd 240 obj->spi->TXCTL |= (1 << 20);
mbed_official 266:69e8a32876bd 241 obj->spi->TXDAT = (value & 0xffff);
mbed_official 103:9b881da47c92 242 }
mbed_official 103:9b881da47c92 243
mbed_official 261:ee1cf08b7bc7 244 static inline int spi_read(spi_t *obj)
mbed_official 261:ee1cf08b7bc7 245 {
mbed_official 103:9b881da47c92 246 while (!spi_readable(obj));
mbed_official 266:69e8a32876bd 247 return obj->spi->RXDAT & 0xffff; // Only the lower 16 bits contain data
mbed_official 103:9b881da47c92 248 }
mbed_official 103:9b881da47c92 249
mbed_official 261:ee1cf08b7bc7 250 int spi_busy(spi_t *obj)
mbed_official 261:ee1cf08b7bc7 251 {
mbed_official 103:9b881da47c92 252 // checking RXOV(Receiver Overrun interrupt flag)
mbed_official 103:9b881da47c92 253 return obj->spi->STAT & (1 << 2);
mbed_official 261:ee1cf08b7bc7 254 }
mbed_official 103:9b881da47c92 255
mbed_official 261:ee1cf08b7bc7 256 int spi_master_write(spi_t *obj, int value)
mbed_official 261:ee1cf08b7bc7 257 {
mbed_official 103:9b881da47c92 258 spi_write(obj, value);
mbed_official 103:9b881da47c92 259 return spi_read(obj);
mbed_official 103:9b881da47c92 260 }
mbed_official 103:9b881da47c92 261
mbed_official 261:ee1cf08b7bc7 262 int spi_slave_receive(spi_t *obj)
mbed_official 261:ee1cf08b7bc7 263 {
mbed_official 103:9b881da47c92 264 return (spi_readable(obj) && !spi_busy(obj)) ? (1) : (0);
mbed_official 103:9b881da47c92 265 }
mbed_official 103:9b881da47c92 266
mbed_official 261:ee1cf08b7bc7 267 int spi_slave_read(spi_t *obj)
mbed_official 261:ee1cf08b7bc7 268 {
mbed_official 266:69e8a32876bd 269 return obj->spi->RXDAT & 0xffff; // Only the lower 16 bits contain data
mbed_official 103:9b881da47c92 270 }
mbed_official 103:9b881da47c92 271
mbed_official 261:ee1cf08b7bc7 272 void spi_slave_write(spi_t *obj, int value)
mbed_official 261:ee1cf08b7bc7 273 {
mbed_official 103:9b881da47c92 274 while (spi_writeable(obj) == 0) ;
mbed_official 103:9b881da47c92 275 obj->spi->TXDAT = value;
mbed_official 103:9b881da47c92 276 }