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:
humlet
Date:
Sun Jun 30 16:34:50 2013 +0000
Revision:
11:f9e72c209510
Parent:
10:3bc89ef62ce7
fix for mbed lib issue 1 (i2c problem) see also https://mbed.org/users/mbed_official/code/mbed/issues/1

Who changed what in which revision?

UserRevisionLine numberNew contents of line
emilmont 10:3bc89ef62ce7 1 /* mbed Microcontroller Library
emilmont 10:3bc89ef62ce7 2 * Copyright (c) 2006-2013 ARM Limited
emilmont 10:3bc89ef62ce7 3 *
emilmont 10:3bc89ef62ce7 4 * Licensed under the Apache License, Version 2.0 (the "License");
emilmont 10:3bc89ef62ce7 5 * you may not use this file except in compliance with the License.
emilmont 10:3bc89ef62ce7 6 * You may obtain a copy of the License at
emilmont 10:3bc89ef62ce7 7 *
emilmont 10:3bc89ef62ce7 8 * http://www.apache.org/licenses/LICENSE-2.0
emilmont 10:3bc89ef62ce7 9 *
emilmont 10:3bc89ef62ce7 10 * Unless required by applicable law or agreed to in writing, software
emilmont 10:3bc89ef62ce7 11 * distributed under the License is distributed on an "AS IS" BASIS,
emilmont 10:3bc89ef62ce7 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
emilmont 10:3bc89ef62ce7 13 * See the License for the specific language governing permissions and
emilmont 10:3bc89ef62ce7 14 * limitations under the License.
emilmont 10:3bc89ef62ce7 15 */
emilmont 10:3bc89ef62ce7 16 #include "spi_api.h"
emilmont 10:3bc89ef62ce7 17
emilmont 10:3bc89ef62ce7 18 #include <math.h>
emilmont 10:3bc89ef62ce7 19
emilmont 10:3bc89ef62ce7 20 #include "cmsis.h"
emilmont 10:3bc89ef62ce7 21 #include "pinmap.h"
emilmont 10:3bc89ef62ce7 22 #include "error.h"
emilmont 10:3bc89ef62ce7 23
emilmont 10:3bc89ef62ce7 24 static const PinMap PinMap_SPI_SCLK[] = {
emilmont 10:3bc89ef62ce7 25 {PTE2, SPI_1, 2},
emilmont 10:3bc89ef62ce7 26 {PTC5, SPI_0, 2},
emilmont 10:3bc89ef62ce7 27 {PTD1, SPI_0, 2},
emilmont 10:3bc89ef62ce7 28 {NC , NC , 0}
emilmont 10:3bc89ef62ce7 29 };
emilmont 10:3bc89ef62ce7 30
emilmont 10:3bc89ef62ce7 31 static const PinMap PinMap_SPI_MOSI[] = {
emilmont 10:3bc89ef62ce7 32 {PTE1, SPI_1, 2},
emilmont 10:3bc89ef62ce7 33 {PTC6, SPI_0, 2},
emilmont 10:3bc89ef62ce7 34 {PTD2, SPI_0, 2},
emilmont 10:3bc89ef62ce7 35 {NC , NC , 0}
emilmont 10:3bc89ef62ce7 36 };
emilmont 10:3bc89ef62ce7 37
emilmont 10:3bc89ef62ce7 38 static const PinMap PinMap_SPI_MISO[] = {
emilmont 10:3bc89ef62ce7 39 {PTE3, SPI_1, 2},
emilmont 10:3bc89ef62ce7 40 {PTC7, SPI_0, 2},
emilmont 10:3bc89ef62ce7 41 {PTD3, SPI_0, 2},
emilmont 10:3bc89ef62ce7 42 {NC , NC , 0}
emilmont 10:3bc89ef62ce7 43 };
emilmont 10:3bc89ef62ce7 44
emilmont 10:3bc89ef62ce7 45 static const PinMap PinMap_SPI_SSEL[] = {
emilmont 10:3bc89ef62ce7 46 {PTE4, SPI_1, 2},
emilmont 10:3bc89ef62ce7 47 {PTC4, SPI_0, 2},
emilmont 10:3bc89ef62ce7 48 {PTD0, SPI_0, 2},
emilmont 10:3bc89ef62ce7 49 {NC , NC , 0}
emilmont 10:3bc89ef62ce7 50 };
emilmont 10:3bc89ef62ce7 51
emilmont 10:3bc89ef62ce7 52 void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel) {
emilmont 10:3bc89ef62ce7 53 // determine the SPI to use
emilmont 10:3bc89ef62ce7 54 SPIName spi_mosi = (SPIName)pinmap_peripheral(mosi, PinMap_SPI_MOSI);
emilmont 10:3bc89ef62ce7 55 SPIName spi_miso = (SPIName)pinmap_peripheral(miso, PinMap_SPI_MISO);
emilmont 10:3bc89ef62ce7 56 SPIName spi_sclk = (SPIName)pinmap_peripheral(sclk, PinMap_SPI_SCLK);
emilmont 10:3bc89ef62ce7 57 SPIName spi_ssel = (SPIName)pinmap_peripheral(ssel, PinMap_SPI_SSEL);
emilmont 10:3bc89ef62ce7 58 SPIName spi_data = (SPIName)pinmap_merge(spi_mosi, spi_miso);
emilmont 10:3bc89ef62ce7 59 SPIName spi_cntl = (SPIName)pinmap_merge(spi_sclk, spi_ssel);
emilmont 10:3bc89ef62ce7 60
emilmont 10:3bc89ef62ce7 61 obj->spi = (SPI_Type*)pinmap_merge(spi_data, spi_cntl);
emilmont 10:3bc89ef62ce7 62 if ((int)obj->spi == NC) {
emilmont 10:3bc89ef62ce7 63 error("SPI pinout mapping failed");
emilmont 10:3bc89ef62ce7 64 }
emilmont 10:3bc89ef62ce7 65
emilmont 10:3bc89ef62ce7 66 // enable power and clocking
emilmont 10:3bc89ef62ce7 67 switch ((int)obj->spi) {
emilmont 10:3bc89ef62ce7 68 case SPI_0: SIM->SCGC5 |= 1 << 11; SIM->SCGC4 |= 1 << 22; break;
emilmont 10:3bc89ef62ce7 69 case SPI_1: SIM->SCGC5 |= 1 << 13; SIM->SCGC4 |= 1 << 23; break;
emilmont 10:3bc89ef62ce7 70 }
emilmont 10:3bc89ef62ce7 71
emilmont 10:3bc89ef62ce7 72 // set default format and frequency
emilmont 10:3bc89ef62ce7 73 if (ssel == NC) {
emilmont 10:3bc89ef62ce7 74 spi_format(obj, 8, 0, 0); // 8 bits, mode 0, master
emilmont 10:3bc89ef62ce7 75 } else {
emilmont 10:3bc89ef62ce7 76 spi_format(obj, 8, 0, 1); // 8 bits, mode 0, slave
emilmont 10:3bc89ef62ce7 77 }
emilmont 10:3bc89ef62ce7 78 spi_frequency(obj, 1000000);
emilmont 10:3bc89ef62ce7 79
emilmont 10:3bc89ef62ce7 80 // enable SPI
emilmont 10:3bc89ef62ce7 81 obj->spi->C1 |= SPI_C1_SPE_MASK;
emilmont 10:3bc89ef62ce7 82
emilmont 10:3bc89ef62ce7 83 // pin out the spi pins
emilmont 10:3bc89ef62ce7 84 pinmap_pinout(mosi, PinMap_SPI_MOSI);
emilmont 10:3bc89ef62ce7 85 pinmap_pinout(miso, PinMap_SPI_MISO);
emilmont 10:3bc89ef62ce7 86 pinmap_pinout(sclk, PinMap_SPI_SCLK);
emilmont 10:3bc89ef62ce7 87 if (ssel != NC) {
emilmont 10:3bc89ef62ce7 88 pinmap_pinout(ssel, PinMap_SPI_SSEL);
emilmont 10:3bc89ef62ce7 89 }
emilmont 10:3bc89ef62ce7 90 }
emilmont 10:3bc89ef62ce7 91
emilmont 10:3bc89ef62ce7 92 void spi_free(spi_t *obj) {
emilmont 10:3bc89ef62ce7 93 // [TODO]
emilmont 10:3bc89ef62ce7 94 }
emilmont 10:3bc89ef62ce7 95 void spi_format(spi_t *obj, int bits, int mode, int slave) {
emilmont 10:3bc89ef62ce7 96 if (bits != 8) {
emilmont 10:3bc89ef62ce7 97 error("Only 8bits SPI supported");
emilmont 10:3bc89ef62ce7 98 }
emilmont 10:3bc89ef62ce7 99
emilmont 10:3bc89ef62ce7 100 if ((mode < 0) || (mode > 3)) {
emilmont 10:3bc89ef62ce7 101 error("SPI mode unsupported");
emilmont 10:3bc89ef62ce7 102 }
emilmont 10:3bc89ef62ce7 103
emilmont 10:3bc89ef62ce7 104 uint8_t polarity = (mode & 0x2) ? 1 : 0;
emilmont 10:3bc89ef62ce7 105 uint8_t phase = (mode & 0x1) ? 1 : 0;
emilmont 10:3bc89ef62ce7 106 uint8_t c1_data = ((!slave) << 4) | (polarity << 3) | (phase << 2);
emilmont 10:3bc89ef62ce7 107
emilmont 10:3bc89ef62ce7 108 // clear MSTR, CPOL and CPHA bits
emilmont 10:3bc89ef62ce7 109 obj->spi->C1 &= ~(0x7 << 2);
emilmont 10:3bc89ef62ce7 110
emilmont 10:3bc89ef62ce7 111 // write new value
emilmont 10:3bc89ef62ce7 112 obj->spi->C1 |= c1_data;
emilmont 10:3bc89ef62ce7 113 }
emilmont 10:3bc89ef62ce7 114
emilmont 10:3bc89ef62ce7 115 void spi_frequency(spi_t *obj, int hz) {
emilmont 10:3bc89ef62ce7 116 uint32_t error = 0;
emilmont 10:3bc89ef62ce7 117 uint32_t p_error = 0xffffffff;
emilmont 10:3bc89ef62ce7 118 uint32_t ref = 0;
emilmont 10:3bc89ef62ce7 119 uint8_t spr = 0;
emilmont 10:3bc89ef62ce7 120 uint8_t ref_spr = 0;
emilmont 10:3bc89ef62ce7 121 uint8_t ref_prescaler = 0;
emilmont 10:3bc89ef62ce7 122
emilmont 10:3bc89ef62ce7 123 // bus clk
emilmont 10:3bc89ef62ce7 124 uint32_t PCLK = 48000000u;
emilmont 10:3bc89ef62ce7 125 uint8_t prescaler = 1;
emilmont 10:3bc89ef62ce7 126 uint8_t divisor = 2;
emilmont 10:3bc89ef62ce7 127
emilmont 10:3bc89ef62ce7 128 for (prescaler = 1; prescaler <= 8; prescaler++) {
emilmont 10:3bc89ef62ce7 129 divisor = 2;
emilmont 10:3bc89ef62ce7 130 for (spr = 0; spr <= 8; spr++) {
emilmont 10:3bc89ef62ce7 131 ref = PCLK / (prescaler*divisor);
emilmont 10:3bc89ef62ce7 132 error = (ref > hz) ? ref - hz : hz - ref;
emilmont 10:3bc89ef62ce7 133 if (error < p_error) {
emilmont 10:3bc89ef62ce7 134 ref_spr = spr;
emilmont 10:3bc89ef62ce7 135 ref_prescaler = prescaler - 1;
emilmont 10:3bc89ef62ce7 136 p_error = error;
emilmont 10:3bc89ef62ce7 137 }
emilmont 10:3bc89ef62ce7 138 divisor *= 2;
emilmont 10:3bc89ef62ce7 139 }
emilmont 10:3bc89ef62ce7 140 }
emilmont 10:3bc89ef62ce7 141
emilmont 10:3bc89ef62ce7 142 // set SPPR and SPR
emilmont 10:3bc89ef62ce7 143 obj->spi->BR = ((ref_prescaler & 0x7) << 4) | (ref_spr & 0xf);
emilmont 10:3bc89ef62ce7 144 }
emilmont 10:3bc89ef62ce7 145
emilmont 10:3bc89ef62ce7 146 static inline int spi_writeable(spi_t * obj) {
emilmont 10:3bc89ef62ce7 147 return (obj->spi->S & SPI_S_SPTEF_MASK) ? 1 : 0;
emilmont 10:3bc89ef62ce7 148 }
emilmont 10:3bc89ef62ce7 149
emilmont 10:3bc89ef62ce7 150 static inline int spi_readable(spi_t * obj) {
emilmont 10:3bc89ef62ce7 151 return (obj->spi->S & SPI_S_SPRF_MASK) ? 1 : 0;
emilmont 10:3bc89ef62ce7 152 }
emilmont 10:3bc89ef62ce7 153
emilmont 10:3bc89ef62ce7 154 int spi_master_write(spi_t *obj, int value) {
emilmont 10:3bc89ef62ce7 155 // wait tx buffer empty
emilmont 10:3bc89ef62ce7 156 while(!spi_writeable(obj));
emilmont 10:3bc89ef62ce7 157 obj->spi->D = (value & 0xff);
emilmont 10:3bc89ef62ce7 158
emilmont 10:3bc89ef62ce7 159 // wait rx buffer full
emilmont 10:3bc89ef62ce7 160 while (!spi_readable(obj));
emilmont 10:3bc89ef62ce7 161 return obj->spi->D & 0xff;
emilmont 10:3bc89ef62ce7 162 }
emilmont 10:3bc89ef62ce7 163
emilmont 10:3bc89ef62ce7 164 int spi_slave_receive(spi_t *obj) {
emilmont 10:3bc89ef62ce7 165 return spi_readable(obj);
emilmont 10:3bc89ef62ce7 166 }
emilmont 10:3bc89ef62ce7 167
emilmont 10:3bc89ef62ce7 168 int spi_slave_read(spi_t *obj) {
emilmont 10:3bc89ef62ce7 169 return obj->spi->D;
emilmont 10:3bc89ef62ce7 170 }
emilmont 10:3bc89ef62ce7 171
emilmont 10:3bc89ef62ce7 172 void spi_slave_write(spi_t *obj, int value) {
emilmont 10:3bc89ef62ce7 173 while (!spi_writeable(obj));
emilmont 10:3bc89ef62ce7 174 obj->spi->D = value;
emilmont 10:3bc89ef62ce7 175 }