Tux Leon / mbed-dev

Fork of mbed-dev by mbed official

Committer:
bogdanm
Date:
Thu Oct 01 15:25:22 2015 +0300
Revision:
0:9b334a45a8ff
Child:
144:ef7eb2e8f9f7
Initial commit on mbed-dev

Replaces mbed-src (now inactive)

Who changed what in which revision?

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