mbed library sources. Supersedes mbed-src.

Fork of mbed by teralytic

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 *******************************************************************************
bogdanm 0:9b334a45a8ff 3 * Copyright (c) 2015 WIZnet Co.,Ltd. All rights reserved.
bogdanm 0:9b334a45a8ff 4 * All rights reserved.
bogdanm 0:9b334a45a8ff 5 *
bogdanm 0:9b334a45a8ff 6 * Redistribution and use in source and binary forms, with or without
bogdanm 0:9b334a45a8ff 7 * modification, are permitted provided that the following conditions are met:
bogdanm 0:9b334a45a8ff 8 *
bogdanm 0:9b334a45a8ff 9 * 1. Redistributions of source code must retain the above copyright notice,
bogdanm 0:9b334a45a8ff 10 * this list of conditions and the following disclaimer.
bogdanm 0:9b334a45a8ff 11 * 2. Redistributions in binary form must reproduce the above copyright notice,
bogdanm 0:9b334a45a8ff 12 * this list of conditions and the following disclaimer in the documentation
bogdanm 0:9b334a45a8ff 13 * and/or other materials provided with the distribution.
bogdanm 0:9b334a45a8ff 14 * 3. Neither the name of ARM Limited nor the names of its contributors
bogdanm 0:9b334a45a8ff 15 * may be used to endorse or promote products derived from this software
bogdanm 0:9b334a45a8ff 16 * without specific prior written permission.
bogdanm 0:9b334a45a8ff 17 *
bogdanm 0:9b334a45a8ff 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
bogdanm 0:9b334a45a8ff 19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
bogdanm 0:9b334a45a8ff 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
bogdanm 0:9b334a45a8ff 21 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
bogdanm 0:9b334a45a8ff 22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
bogdanm 0:9b334a45a8ff 23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
bogdanm 0:9b334a45a8ff 24 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
bogdanm 0:9b334a45a8ff 25 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
bogdanm 0:9b334a45a8ff 26 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
bogdanm 0:9b334a45a8ff 27 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
bogdanm 0:9b334a45a8ff 28 *******************************************************************************
bogdanm 0:9b334a45a8ff 29 */
bogdanm 0:9b334a45a8ff 30
bogdanm 0:9b334a45a8ff 31 #include "mbed_assert.h"
bogdanm 0:9b334a45a8ff 32 #include <math.h>
bogdanm 0:9b334a45a8ff 33
bogdanm 0:9b334a45a8ff 34 #include "spi_api.h"
bogdanm 0:9b334a45a8ff 35 #include "cmsis.h"
bogdanm 0:9b334a45a8ff 36 #include "pinmap.h"
bogdanm 0:9b334a45a8ff 37 #include "mbed_error.h"
bogdanm 0:9b334a45a8ff 38 #include "PeripheralPins.h"
bogdanm 0:9b334a45a8ff 39
bogdanm 0:9b334a45a8ff 40 static inline int ssp_disable(spi_t *obj);
bogdanm 0:9b334a45a8ff 41 static inline int ssp_enable(spi_t *obj);
bogdanm 0:9b334a45a8ff 42
bogdanm 0:9b334a45a8ff 43 void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel) {
bogdanm 0:9b334a45a8ff 44 // determine the SPI to use
bogdanm 0:9b334a45a8ff 45 SPIName spi_mosi = (SPIName)pinmap_peripheral(mosi, PinMap_SPI_MOSI);
bogdanm 0:9b334a45a8ff 46 SPIName spi_miso = (SPIName)pinmap_peripheral(miso, PinMap_SPI_MISO);
bogdanm 0:9b334a45a8ff 47 SPIName spi_sclk = (SPIName)pinmap_peripheral(sclk, PinMap_SPI_SCLK);
bogdanm 0:9b334a45a8ff 48 SPIName spi_ssel = (SPIName)pinmap_peripheral(ssel, PinMap_SPI_SSEL);
bogdanm 0:9b334a45a8ff 49 SPIName spi_data = (SPIName)pinmap_merge(spi_mosi, spi_miso);
bogdanm 0:9b334a45a8ff 50 SPIName spi_cntl = (SPIName)pinmap_merge(spi_sclk, spi_ssel);
bogdanm 0:9b334a45a8ff 51 obj->spi = (SSP_TypeDef*)pinmap_merge(spi_data, spi_cntl);
bogdanm 0:9b334a45a8ff 52 MBED_ASSERT((int)obj->spi != NC);
bogdanm 0:9b334a45a8ff 53
bogdanm 0:9b334a45a8ff 54 // enable power and clocking
bogdanm 0:9b334a45a8ff 55 switch ((int)obj->spi) {
bogdanm 0:9b334a45a8ff 56 case SPI_0: CRG->SSPCLK_SSR = CRG_SSPCLK_SSR_MCLK; break; //PLL output clock
bogdanm 0:9b334a45a8ff 57 case SPI_1: CRG->SSPCLK_SSR = CRG_SSPCLK_SSR_MCLK; break;
bogdanm 0:9b334a45a8ff 58 }
bogdanm 0:9b334a45a8ff 59
bogdanm 0:9b334a45a8ff 60 // set default format and frequency
bogdanm 0:9b334a45a8ff 61 if (ssel == NC) {
bogdanm 0:9b334a45a8ff 62 spi_format(obj, 8, 0, 0); // 8 bits, mode 0, master
bogdanm 0:9b334a45a8ff 63 } else {
bogdanm 0:9b334a45a8ff 64 spi_format(obj, 8, 0, 1); // 8 bits, mode 0, slave
bogdanm 0:9b334a45a8ff 65 }
bogdanm 0:9b334a45a8ff 66 spi_frequency(obj, 1000000);
bogdanm 0:9b334a45a8ff 67
bogdanm 0:9b334a45a8ff 68 // enable the ssp channel
bogdanm 0:9b334a45a8ff 69 ssp_enable(obj);
bogdanm 0:9b334a45a8ff 70
bogdanm 0:9b334a45a8ff 71 // pin out the spi pins
bogdanm 0:9b334a45a8ff 72 pinmap_pinout(mosi, PinMap_SPI_MOSI);
bogdanm 0:9b334a45a8ff 73 pinmap_pinout(miso, PinMap_SPI_MISO);
bogdanm 0:9b334a45a8ff 74 pinmap_pinout(sclk, PinMap_SPI_SCLK);
bogdanm 0:9b334a45a8ff 75 if (ssel != NC) {
bogdanm 0:9b334a45a8ff 76 pinmap_pinout(ssel, PinMap_SPI_SSEL);
bogdanm 0:9b334a45a8ff 77 }
bogdanm 0:9b334a45a8ff 78 }
bogdanm 0:9b334a45a8ff 79
bogdanm 0:9b334a45a8ff 80 void spi_free(spi_t *obj) {}
bogdanm 0:9b334a45a8ff 81
bogdanm 0:9b334a45a8ff 82 void spi_format(spi_t *obj, int bits, int mode, int slave) {
bogdanm 0:9b334a45a8ff 83 ssp_disable(obj);
bogdanm 0:9b334a45a8ff 84 MBED_ASSERT(((bits >= 4) && (bits <= 16)) && (mode >= 0 && mode <= 3));
bogdanm 0:9b334a45a8ff 85
bogdanm 0:9b334a45a8ff 86 int polarity = (mode & 0x2) ? 1 : 0;
bogdanm 0:9b334a45a8ff 87 int phase = (mode & 0x1) ? 1 : 0;
bogdanm 0:9b334a45a8ff 88
bogdanm 0:9b334a45a8ff 89 // set it up
bogdanm 0:9b334a45a8ff 90 int DSS = bits - 1; // DSS (data select size)
bogdanm 0:9b334a45a8ff 91 int SPO = (polarity) ? 1 : 0; // SPO - clock out polarity
bogdanm 0:9b334a45a8ff 92 int SPH = (phase) ? 1 : 0; // SPH - clock out phase
bogdanm 0:9b334a45a8ff 93
bogdanm 0:9b334a45a8ff 94 int FRF = 0; // FRF (frame format) = SPI
bogdanm 0:9b334a45a8ff 95 uint32_t tmp = obj->spi->CR0;
bogdanm 0:9b334a45a8ff 96 tmp &= ~(0xFFFF);
bogdanm 0:9b334a45a8ff 97 tmp |= DSS << 0
bogdanm 0:9b334a45a8ff 98 | FRF << 4
bogdanm 0:9b334a45a8ff 99 | SPO << 6
bogdanm 0:9b334a45a8ff 100 | SPH << 7;
bogdanm 0:9b334a45a8ff 101 obj->spi->CR0 = tmp;
bogdanm 0:9b334a45a8ff 102
bogdanm 0:9b334a45a8ff 103 tmp = obj->spi->CR1;
bogdanm 0:9b334a45a8ff 104 tmp &= ~(0xD);
bogdanm 0:9b334a45a8ff 105 tmp |= 0 << 0 // LBM - loop back mode - off
bogdanm 0:9b334a45a8ff 106 | ((slave) ? 1 : 0) << 2 // MS - master slave mode, 1 = slave
bogdanm 0:9b334a45a8ff 107 | 0 << 3; // SOD - slave output disable - na
bogdanm 0:9b334a45a8ff 108 obj->spi->CR1 = tmp;
bogdanm 0:9b334a45a8ff 109
bogdanm 0:9b334a45a8ff 110 ssp_enable(obj);
bogdanm 0:9b334a45a8ff 111 }
bogdanm 0:9b334a45a8ff 112
bogdanm 0:9b334a45a8ff 113 void spi_frequency(spi_t *obj, int hz) {
bogdanm 0:9b334a45a8ff 114 ssp_disable(obj);
bogdanm 0:9b334a45a8ff 115
bogdanm 0:9b334a45a8ff 116 // setup the spi clock diveder to /1
bogdanm 0:9b334a45a8ff 117 switch ((int)obj->spi) {
bogdanm 0:9b334a45a8ff 118 case SPI_0:
bogdanm 0:9b334a45a8ff 119 CRG->SSPCLK_PVSR = CRG_SSPCLK_PVSR_DIV1; //1/1 (bypass)
bogdanm 0:9b334a45a8ff 120 break;
bogdanm 0:9b334a45a8ff 121 case SPI_1:
bogdanm 0:9b334a45a8ff 122 CRG->SSPCLK_PVSR = CRG_SSPCLK_PVSR_DIV1; //1/1 (bypass)
bogdanm 0:9b334a45a8ff 123 break;
bogdanm 0:9b334a45a8ff 124 }
bogdanm 0:9b334a45a8ff 125
bogdanm 0:9b334a45a8ff 126 uint32_t HCLK = SystemCoreClock;
bogdanm 0:9b334a45a8ff 127
bogdanm 0:9b334a45a8ff 128 int prescaler;
bogdanm 0:9b334a45a8ff 129
bogdanm 0:9b334a45a8ff 130 for (prescaler = 2; prescaler <= 254; prescaler += 2) {
bogdanm 0:9b334a45a8ff 131 int prescale_hz = HCLK / prescaler;
bogdanm 0:9b334a45a8ff 132
bogdanm 0:9b334a45a8ff 133 // calculate the divider
bogdanm 0:9b334a45a8ff 134 int divider = floor(((float)prescale_hz / (float)hz) + 0.5f);
bogdanm 0:9b334a45a8ff 135
bogdanm 0:9b334a45a8ff 136 // check we can support the divider
bogdanm 0:9b334a45a8ff 137 if (divider < 256) {
bogdanm 0:9b334a45a8ff 138 // prescaler
bogdanm 0:9b334a45a8ff 139 obj->spi->CPSR = prescaler;
bogdanm 0:9b334a45a8ff 140
bogdanm 0:9b334a45a8ff 141 // divider
bogdanm 0:9b334a45a8ff 142 obj->spi->CR0 &= ~(0xFFFF << 8);
bogdanm 0:9b334a45a8ff 143 obj->spi->CR0 |= (divider - 1) << 8;
bogdanm 0:9b334a45a8ff 144 ssp_enable(obj);
bogdanm 0:9b334a45a8ff 145 return;
bogdanm 0:9b334a45a8ff 146 }
bogdanm 0:9b334a45a8ff 147 }
bogdanm 0:9b334a45a8ff 148 error("Couldn't setup requested SPI frequency");
bogdanm 0:9b334a45a8ff 149 }
bogdanm 0:9b334a45a8ff 150
bogdanm 0:9b334a45a8ff 151 static inline int ssp_disable(spi_t *obj) {
bogdanm 0:9b334a45a8ff 152 return obj->spi->CR1 &= ~(1 << 1);
bogdanm 0:9b334a45a8ff 153 }
bogdanm 0:9b334a45a8ff 154
bogdanm 0:9b334a45a8ff 155 static inline int ssp_enable(spi_t *obj) {
bogdanm 0:9b334a45a8ff 156 return obj->spi->CR1 |= (1 << 1);
bogdanm 0:9b334a45a8ff 157 }
bogdanm 0:9b334a45a8ff 158
bogdanm 0:9b334a45a8ff 159 static inline int ssp_readable(spi_t *obj) {
bogdanm 0:9b334a45a8ff 160 return obj->spi->SR & (1 << 2);
bogdanm 0:9b334a45a8ff 161 }
bogdanm 0:9b334a45a8ff 162
bogdanm 0:9b334a45a8ff 163 static inline int ssp_writeable(spi_t *obj) {
bogdanm 0:9b334a45a8ff 164 return obj->spi->SR & (1 << 1);
bogdanm 0:9b334a45a8ff 165 }
bogdanm 0:9b334a45a8ff 166
bogdanm 0:9b334a45a8ff 167 static inline void ssp_write(spi_t *obj, int value) {
bogdanm 0:9b334a45a8ff 168 while (!ssp_writeable(obj));
bogdanm 0:9b334a45a8ff 169 obj->spi->DR = value;
bogdanm 0:9b334a45a8ff 170 }
bogdanm 0:9b334a45a8ff 171
bogdanm 0:9b334a45a8ff 172 static inline int ssp_read(spi_t *obj) {
bogdanm 0:9b334a45a8ff 173 while (!ssp_readable(obj));
bogdanm 0:9b334a45a8ff 174 return obj->spi->DR;
bogdanm 0:9b334a45a8ff 175 }
bogdanm 0:9b334a45a8ff 176
bogdanm 0:9b334a45a8ff 177 static inline int ssp_busy(spi_t *obj) {
bogdanm 0:9b334a45a8ff 178 return (obj->spi->SR & (1 << 4)) ? (1) : (0);
bogdanm 0:9b334a45a8ff 179 }
bogdanm 0:9b334a45a8ff 180
bogdanm 0:9b334a45a8ff 181 int spi_master_write(spi_t *obj, int value) {
bogdanm 0:9b334a45a8ff 182 ssp_write(obj, value);
bogdanm 0:9b334a45a8ff 183 return ssp_read(obj);
bogdanm 0:9b334a45a8ff 184 }
bogdanm 0:9b334a45a8ff 185
bogdanm 0:9b334a45a8ff 186 int spi_slave_receive(spi_t *obj) {
bogdanm 0:9b334a45a8ff 187 return (ssp_readable(obj) && !ssp_busy(obj)) ? (1) : (0);
bogdanm 0:9b334a45a8ff 188 }
bogdanm 0:9b334a45a8ff 189
bogdanm 0:9b334a45a8ff 190 int spi_slave_read(spi_t *obj) {
bogdanm 0:9b334a45a8ff 191 return obj->spi->DR;
bogdanm 0:9b334a45a8ff 192 }
bogdanm 0:9b334a45a8ff 193
bogdanm 0:9b334a45a8ff 194 void spi_slave_write(spi_t *obj, int value) {
bogdanm 0:9b334a45a8ff 195 while (ssp_writeable(obj) == 0) ;
bogdanm 0:9b334a45a8ff 196 obj->spi->DR = value;
bogdanm 0:9b334a45a8ff 197 }
bogdanm 0:9b334a45a8ff 198
bogdanm 0:9b334a45a8ff 199 int spi_busy(spi_t *obj) {
bogdanm 0:9b334a45a8ff 200 return ssp_busy(obj);
bogdanm 0:9b334a45a8ff 201 }
bogdanm 0:9b334a45a8ff 202