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:
Mon Nov 11 13:30:09 2013 +0000
Revision:
46:bebbbd80dd87
Child:
69:49e45cb70de1
Synchronized with git revision b2733e9b9af906952b295cd6abcf916bf79780ab

Who changed what in which revision?

UserRevisionLine numberNew contents of line
mbed_official 46:bebbbd80dd87 1 /* mbed Microcontroller Library
mbed_official 46:bebbbd80dd87 2 * Copyright (c) 2006-2013 ARM Limited
mbed_official 46:bebbbd80dd87 3 *
mbed_official 46:bebbbd80dd87 4 * Licensed under the Apache License, Version 2.0 (the "License");
mbed_official 46:bebbbd80dd87 5 * you may not use this file except in compliance with the License.
mbed_official 46:bebbbd80dd87 6 * You may obtain a copy of the License at
mbed_official 46:bebbbd80dd87 7 *
mbed_official 46:bebbbd80dd87 8 * http://www.apache.org/licenses/LICENSE-2.0
mbed_official 46:bebbbd80dd87 9 *
mbed_official 46:bebbbd80dd87 10 * Unless required by applicable law or agreed to in writing, software
mbed_official 46:bebbbd80dd87 11 * distributed under the License is distributed on an "AS IS" BASIS,
mbed_official 46:bebbbd80dd87 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
mbed_official 46:bebbbd80dd87 13 * See the License for the specific language governing permissions and
mbed_official 46:bebbbd80dd87 14 * limitations under the License.
mbed_official 46:bebbbd80dd87 15 */
mbed_official 46:bebbbd80dd87 16 #include <math.h>
mbed_official 46:bebbbd80dd87 17
mbed_official 46:bebbbd80dd87 18 #include "spi_api.h"
mbed_official 46:bebbbd80dd87 19 #include "cmsis.h"
mbed_official 46:bebbbd80dd87 20 #include "pinmap.h"
mbed_official 46:bebbbd80dd87 21 #include "error.h"
mbed_official 46:bebbbd80dd87 22
mbed_official 46:bebbbd80dd87 23 static const SWM_Map SWM_SPI_SSEL[] = {
mbed_official 46:bebbbd80dd87 24 {4, 16},
mbed_official 46:bebbbd80dd87 25 {5, 16},
mbed_official 46:bebbbd80dd87 26 };
mbed_official 46:bebbbd80dd87 27
mbed_official 46:bebbbd80dd87 28 static const SWM_Map SWM_SPI_SCLK[] = {
mbed_official 46:bebbbd80dd87 29 {3, 24},
mbed_official 46:bebbbd80dd87 30 {4, 24},
mbed_official 46:bebbbd80dd87 31 };
mbed_official 46:bebbbd80dd87 32
mbed_official 46:bebbbd80dd87 33 static const SWM_Map SWM_SPI_MOSI[] = {
mbed_official 46:bebbbd80dd87 34 {4, 0},
mbed_official 46:bebbbd80dd87 35 {5, 0},
mbed_official 46:bebbbd80dd87 36 };
mbed_official 46:bebbbd80dd87 37
mbed_official 46:bebbbd80dd87 38 static const SWM_Map SWM_SPI_MISO[] = {
mbed_official 46:bebbbd80dd87 39 {4, 8},
mbed_official 46:bebbbd80dd87 40 {5, 16},
mbed_official 46:bebbbd80dd87 41 };
mbed_official 46:bebbbd80dd87 42
mbed_official 46:bebbbd80dd87 43 // bit flags for used SPIs
mbed_official 46:bebbbd80dd87 44 static unsigned char spi_used = 0;
mbed_official 46:bebbbd80dd87 45 static int get_available_spi(void) {
mbed_official 46:bebbbd80dd87 46 int i;
mbed_official 46:bebbbd80dd87 47 for (i=0; i<2; i++) {
mbed_official 46:bebbbd80dd87 48 if ((spi_used & (1 << i)) == 0)
mbed_official 46:bebbbd80dd87 49 return i;
mbed_official 46:bebbbd80dd87 50 }
mbed_official 46:bebbbd80dd87 51 return -1;
mbed_official 46:bebbbd80dd87 52 }
mbed_official 46:bebbbd80dd87 53
mbed_official 46:bebbbd80dd87 54 static inline int ssp_disable(spi_t *obj);
mbed_official 46:bebbbd80dd87 55 static inline int ssp_enable(spi_t *obj);
mbed_official 46:bebbbd80dd87 56
mbed_official 46:bebbbd80dd87 57 void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel) {
mbed_official 46:bebbbd80dd87 58 int spi_n = get_available_spi();
mbed_official 46:bebbbd80dd87 59 if (spi_n == -1) {
mbed_official 46:bebbbd80dd87 60 error("No available SPI");
mbed_official 46:bebbbd80dd87 61 }
mbed_official 46:bebbbd80dd87 62 obj->spi_n = spi_n;
mbed_official 46:bebbbd80dd87 63 spi_used |= (1 << spi_n);
mbed_official 46:bebbbd80dd87 64
mbed_official 46:bebbbd80dd87 65 obj->spi = (spi_n) ? (LPC_SPI_TypeDef *)(LPC_SPI1_BASE) : (LPC_SPI_TypeDef *)(LPC_SPI0_BASE);
mbed_official 46:bebbbd80dd87 66
mbed_official 46:bebbbd80dd87 67 const SWM_Map *swm;
mbed_official 46:bebbbd80dd87 68 uint32_t regVal;
mbed_official 46:bebbbd80dd87 69
mbed_official 46:bebbbd80dd87 70 swm = &SWM_SPI_SCLK[obj->spi_n];
mbed_official 46:bebbbd80dd87 71 regVal = LPC_SWM->PINASSIGN[swm->n] & ~(0xFF << swm->offset);
mbed_official 46:bebbbd80dd87 72 LPC_SWM->PINASSIGN[swm->n] = regVal | (sclk << swm->offset);
mbed_official 46:bebbbd80dd87 73
mbed_official 46:bebbbd80dd87 74 swm = &SWM_SPI_MOSI[obj->spi_n];
mbed_official 46:bebbbd80dd87 75 regVal = LPC_SWM->PINASSIGN[swm->n] & ~(0xFF << swm->offset);
mbed_official 46:bebbbd80dd87 76 LPC_SWM->PINASSIGN[swm->n] = regVal | (mosi << swm->offset);
mbed_official 46:bebbbd80dd87 77
mbed_official 46:bebbbd80dd87 78 swm = &SWM_SPI_MISO[obj->spi_n];
mbed_official 46:bebbbd80dd87 79 regVal = LPC_SWM->PINASSIGN[swm->n] & ~(0xFF << swm->offset);
mbed_official 46:bebbbd80dd87 80 LPC_SWM->PINASSIGN[swm->n] = regVal | (miso << swm->offset);
mbed_official 46:bebbbd80dd87 81
mbed_official 46:bebbbd80dd87 82 swm = &SWM_SPI_SSEL[obj->spi_n];
mbed_official 46:bebbbd80dd87 83 regVal = LPC_SWM->PINASSIGN[swm->n] & ~(0xFF << swm->offset);
mbed_official 46:bebbbd80dd87 84 LPC_SWM->PINASSIGN[swm->n] = regVal | (ssel << swm->offset);
mbed_official 46:bebbbd80dd87 85
mbed_official 46:bebbbd80dd87 86 // clear interrupts
mbed_official 46:bebbbd80dd87 87 obj->spi->INTENCLR = 0x3f;
mbed_official 46:bebbbd80dd87 88
mbed_official 46:bebbbd80dd87 89 // enable power and clocking
mbed_official 46:bebbbd80dd87 90 switch (obj->spi_n) {
mbed_official 46:bebbbd80dd87 91 case 0:
mbed_official 46:bebbbd80dd87 92 LPC_SYSCON->SYSAHBCLKCTRL |= (1<<11);
mbed_official 46:bebbbd80dd87 93 LPC_SYSCON->PRESETCTRL &= ~(0x1<<0);
mbed_official 46:bebbbd80dd87 94 LPC_SYSCON->PRESETCTRL |= (0x1<<0);
mbed_official 46:bebbbd80dd87 95 break;
mbed_official 46:bebbbd80dd87 96 case 1:
mbed_official 46:bebbbd80dd87 97 LPC_SYSCON->SYSAHBCLKCTRL |= (1<<12);
mbed_official 46:bebbbd80dd87 98 LPC_SYSCON->PRESETCTRL &= ~(0x1<<1);
mbed_official 46:bebbbd80dd87 99 LPC_SYSCON->PRESETCTRL |= (0x1<<1);
mbed_official 46:bebbbd80dd87 100 break;
mbed_official 46:bebbbd80dd87 101 }
mbed_official 46:bebbbd80dd87 102
mbed_official 46:bebbbd80dd87 103 // set default format and frequency
mbed_official 46:bebbbd80dd87 104 if (ssel == NC) {
mbed_official 46:bebbbd80dd87 105 spi_format(obj, 8, 0, 0); // 8 bits, mode 0, master
mbed_official 46:bebbbd80dd87 106 } else {
mbed_official 46:bebbbd80dd87 107 spi_format(obj, 8, 0, 1); // 8 bits, mode 0, slave
mbed_official 46:bebbbd80dd87 108 }
mbed_official 46:bebbbd80dd87 109 spi_frequency(obj, 1000000);
mbed_official 46:bebbbd80dd87 110
mbed_official 46:bebbbd80dd87 111 // enable the ssp channel
mbed_official 46:bebbbd80dd87 112 ssp_enable(obj);
mbed_official 46:bebbbd80dd87 113 }
mbed_official 46:bebbbd80dd87 114
mbed_official 46:bebbbd80dd87 115 void spi_free(spi_t *obj) {}
mbed_official 46:bebbbd80dd87 116
mbed_official 46:bebbbd80dd87 117 void spi_format(spi_t *obj, int bits, int mode, int slave) {
mbed_official 46:bebbbd80dd87 118 ssp_disable(obj);
mbed_official 46:bebbbd80dd87 119
mbed_official 46:bebbbd80dd87 120 if (!(bits >= 1 && bits <= 16) || !(mode >= 0 && mode <= 3)) {
mbed_official 46:bebbbd80dd87 121 error("SPI format error");
mbed_official 46:bebbbd80dd87 122 }
mbed_official 46:bebbbd80dd87 123
mbed_official 46:bebbbd80dd87 124
mbed_official 46:bebbbd80dd87 125 int polarity = (mode & 0x2) ? 1 : 0;
mbed_official 46:bebbbd80dd87 126 int phase = (mode & 0x1) ? 1 : 0;
mbed_official 46:bebbbd80dd87 127
mbed_official 46:bebbbd80dd87 128 // set it up
mbed_official 46:bebbbd80dd87 129 int DSS = bits - 1; // DSS (data select size)
mbed_official 46:bebbbd80dd87 130 int SPO = (polarity) ? 1 : 0; // SPO - clock out polarity
mbed_official 46:bebbbd80dd87 131 int SPH = (phase) ? 1 : 0; // SPH - clock out phase
mbed_official 46:bebbbd80dd87 132
mbed_official 46:bebbbd80dd87 133 uint32_t tmp = obj->spi->CFG;
mbed_official 46:bebbbd80dd87 134 tmp &= ~((1 << 2) | (1 << 4) | (1 << 5));
mbed_official 46:bebbbd80dd87 135 tmp |= (SPH << 4) | (SPO << 5) | ((slave ? 0 : 1) << 2);
mbed_official 46:bebbbd80dd87 136 obj->spi->CFG = tmp;
mbed_official 46:bebbbd80dd87 137
mbed_official 46:bebbbd80dd87 138 // select frame length
mbed_official 46:bebbbd80dd87 139 tmp = obj->spi->TXDATCTL;
mbed_official 46:bebbbd80dd87 140 tmp &= ~(0xf << 24);
mbed_official 46:bebbbd80dd87 141 tmp |= (DSS << 24);
mbed_official 46:bebbbd80dd87 142 obj->spi->TXDATCTL = tmp;
mbed_official 46:bebbbd80dd87 143
mbed_official 46:bebbbd80dd87 144 ssp_enable(obj);
mbed_official 46:bebbbd80dd87 145 }
mbed_official 46:bebbbd80dd87 146
mbed_official 46:bebbbd80dd87 147 void spi_frequency(spi_t *obj, int hz) {
mbed_official 46:bebbbd80dd87 148 ssp_disable(obj);
mbed_official 46:bebbbd80dd87 149
mbed_official 46:bebbbd80dd87 150 uint32_t PCLK = SystemCoreClock;
mbed_official 46:bebbbd80dd87 151
mbed_official 46:bebbbd80dd87 152 obj->spi->DIV = PCLK/hz - 1;
mbed_official 46:bebbbd80dd87 153 obj->spi->DLY = 0;
mbed_official 46:bebbbd80dd87 154 ssp_enable(obj);
mbed_official 46:bebbbd80dd87 155 }
mbed_official 46:bebbbd80dd87 156
mbed_official 46:bebbbd80dd87 157 static inline int ssp_disable(spi_t *obj) {
mbed_official 46:bebbbd80dd87 158 return obj->spi->CFG &= ~(1 << 0);
mbed_official 46:bebbbd80dd87 159 }
mbed_official 46:bebbbd80dd87 160
mbed_official 46:bebbbd80dd87 161 static inline int ssp_enable(spi_t *obj) {
mbed_official 46:bebbbd80dd87 162 return obj->spi->CFG |= (1 << 0);
mbed_official 46:bebbbd80dd87 163 }
mbed_official 46:bebbbd80dd87 164
mbed_official 46:bebbbd80dd87 165 static inline int ssp_readable(spi_t *obj) {
mbed_official 46:bebbbd80dd87 166 return obj->spi->STAT & (1 << 0);
mbed_official 46:bebbbd80dd87 167 }
mbed_official 46:bebbbd80dd87 168
mbed_official 46:bebbbd80dd87 169 static inline int ssp_writeable(spi_t *obj) {
mbed_official 46:bebbbd80dd87 170 return obj->spi->STAT & (1 << 1);
mbed_official 46:bebbbd80dd87 171 }
mbed_official 46:bebbbd80dd87 172
mbed_official 46:bebbbd80dd87 173 static inline void ssp_write(spi_t *obj, int value) {
mbed_official 46:bebbbd80dd87 174 while (!ssp_writeable(obj));
mbed_official 46:bebbbd80dd87 175 // end of transfer
mbed_official 46:bebbbd80dd87 176 obj->spi->TXDATCTL |= (1 << 20);
mbed_official 46:bebbbd80dd87 177 obj->spi->TXDAT = value;
mbed_official 46:bebbbd80dd87 178 }
mbed_official 46:bebbbd80dd87 179
mbed_official 46:bebbbd80dd87 180 static inline int ssp_read(spi_t *obj) {
mbed_official 46:bebbbd80dd87 181 while (!ssp_readable(obj));
mbed_official 46:bebbbd80dd87 182 return obj->spi->RXDAT;
mbed_official 46:bebbbd80dd87 183 }
mbed_official 46:bebbbd80dd87 184
mbed_official 46:bebbbd80dd87 185 static inline int ssp_busy(spi_t *obj) {
mbed_official 46:bebbbd80dd87 186 // TODO
mbed_official 46:bebbbd80dd87 187 return 0;
mbed_official 46:bebbbd80dd87 188 }
mbed_official 46:bebbbd80dd87 189
mbed_official 46:bebbbd80dd87 190 int spi_master_write(spi_t *obj, int value) {
mbed_official 46:bebbbd80dd87 191 ssp_write(obj, value);
mbed_official 46:bebbbd80dd87 192 return ssp_read(obj);
mbed_official 46:bebbbd80dd87 193 }
mbed_official 46:bebbbd80dd87 194
mbed_official 46:bebbbd80dd87 195 int spi_slave_receive(spi_t *obj) {
mbed_official 46:bebbbd80dd87 196 return (ssp_readable(obj) && !ssp_busy(obj)) ? (1) : (0);
mbed_official 46:bebbbd80dd87 197 };
mbed_official 46:bebbbd80dd87 198
mbed_official 46:bebbbd80dd87 199 int spi_slave_read(spi_t *obj) {
mbed_official 46:bebbbd80dd87 200 return obj->spi->RXDAT;
mbed_official 46:bebbbd80dd87 201 }
mbed_official 46:bebbbd80dd87 202
mbed_official 46:bebbbd80dd87 203 void spi_slave_write(spi_t *obj, int value) {
mbed_official 46:bebbbd80dd87 204 while (ssp_writeable(obj) == 0) ;
mbed_official 46:bebbbd80dd87 205 obj->spi->TXDAT = value;
mbed_official 46:bebbbd80dd87 206 }
mbed_official 46:bebbbd80dd87 207
mbed_official 46:bebbbd80dd87 208 int spi_busy(spi_t *obj) {
mbed_official 46:bebbbd80dd87 209 return ssp_busy(obj);
mbed_official 46:bebbbd80dd87 210 }