Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of mbed-src by
spi_api.c
00001 /* mbed Microcontroller Library 00002 * Copyright (c) 2006-2013 ARM Limited 00003 * 00004 * Licensed under the Apache License, Version 2.0 (the "License"); 00005 * you may not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at 00007 * 00008 * http://www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an "AS IS" BASIS, 00012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 00015 */ 00016 #include <math.h> 00017 00018 #include "spi_api.h" 00019 #include "cmsis.h" 00020 #include "pinmap.h" 00021 #include "error.h" 00022 00023 static const PinMap PinMap_SPI_SCLK[] = { 00024 {P0_7 , SPI_1, 2}, 00025 {P0_15, SPI_0, 2}, 00026 {P1_0, SPI_2, 4}, 00027 {P1_19, SPI_1, 5}, 00028 {P1_20, SPI_0, 5}, 00029 {P1_31, SPI_1, 2}, 00030 {P2_22, SPI_0, 2}, 00031 {P4_20, SPI_1, 3}, 00032 {P5_2, SPI_2, 2}, 00033 {NC , NC , 0} 00034 }; 00035 00036 static const PinMap PinMap_SPI_MOSI[] = { 00037 {P0_9 , SPI_1, 2}, 00038 {P0_13, SPI_1, 2}, 00039 {P0_18, SPI_0, 2}, 00040 {P1_1, SPI_2, 4}, 00041 {P1_22, SPI_1, 5}, 00042 {P1_24, SPI_0, 5}, 00043 {P2_27, SPI_0, 2}, 00044 {P4_23, SPI_1, 3}, 00045 {P5_0, SPI_2, 2}, 00046 {NC , NC , 0} 00047 }; 00048 00049 static const PinMap PinMap_SPI_MISO[] = { 00050 {P0_8 , SPI_1, 2}, 00051 {P0_12, SPI_1, 2}, 00052 {P0_17, SPI_0, 2}, 00053 {P1_4, SPI_2, 4}, 00054 {P1_18, SPI_1, 5}, 00055 {P1_23, SPI_0, 5}, 00056 {P2_26, SPI_0, 2}, 00057 {P4_22, SPI_1, 3}, 00058 {P5_1, SPI_2, 2}, 00059 {NC , NC , 0} 00060 }; 00061 00062 static const PinMap PinMap_SPI_SSEL[] = { 00063 {P0_6 , SPI_1, 2}, 00064 {P0_14, SPI_1, 2}, 00065 {P0_16, SPI_0, 2}, 00066 {P1_8, SPI_2, 4}, 00067 {P1_21, SPI_0, 3}, 00068 {P1_26, SPI_1, 5}, 00069 {P1_28, SPI_0, 5}, 00070 {P2_23, SPI_0, 2}, 00071 {P4_21, SPI_1, 3}, 00072 {NC , NC , 0} 00073 }; 00074 00075 static inline int ssp_disable(spi_t *obj); 00076 static inline int ssp_enable(spi_t *obj); 00077 00078 void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel) { 00079 // determine the SPI to use 00080 SPIName spi_mosi = (SPIName)pinmap_peripheral(mosi, PinMap_SPI_MOSI); 00081 SPIName spi_miso = (SPIName)pinmap_peripheral(miso, PinMap_SPI_MISO); 00082 SPIName spi_sclk = (SPIName)pinmap_peripheral(sclk, PinMap_SPI_SCLK); 00083 SPIName spi_ssel = (SPIName)pinmap_peripheral(ssel, PinMap_SPI_SSEL); 00084 SPIName spi_data = (SPIName)pinmap_merge(spi_mosi, spi_miso); 00085 SPIName spi_cntl = (SPIName)pinmap_merge(spi_sclk, spi_ssel); 00086 obj->spi = (LPC_SSP_TypeDef*)pinmap_merge(spi_data, spi_cntl); 00087 if ((int)obj->spi == NC) { 00088 error("SPI pinout mapping failed"); 00089 } 00090 00091 // enable power and clocking 00092 switch ((int)obj->spi) { 00093 case SPI_0: LPC_SC->PCONP |= 1 << 21; break; 00094 case SPI_1: LPC_SC->PCONP |= 1 << 10; break; 00095 case SPI_2: LPC_SC->PCONP |= 1 << 20; break; 00096 } 00097 00098 // set default format and frequency 00099 if (ssel == NC) { 00100 spi_format(obj, 8, 0, 0); // 8 bits, mode 0, master 00101 } else { 00102 spi_format(obj, 8, 0, 1); // 8 bits, mode 0, slave 00103 } 00104 spi_frequency(obj, 1000000); 00105 00106 // enable the ssp channel 00107 ssp_enable(obj); 00108 00109 // pin out the spi pins 00110 pinmap_pinout(mosi, PinMap_SPI_MOSI); 00111 pinmap_pinout(miso, PinMap_SPI_MISO); 00112 pinmap_pinout(sclk, PinMap_SPI_SCLK); 00113 if (ssel != NC) { 00114 pinmap_pinout(ssel, PinMap_SPI_SSEL); 00115 } 00116 } 00117 00118 void spi_free(spi_t *obj) {} 00119 00120 void spi_format(spi_t *obj, int bits, int mode, int slave) { 00121 ssp_disable(obj); 00122 00123 if (!(bits >= 4 && bits <= 16) || !(mode >= 0 && mode <= 3)) { 00124 error("SPI format error"); 00125 } 00126 00127 int polarity = (mode & 0x2) ? 1 : 0; 00128 int phase = (mode & 0x1) ? 1 : 0; 00129 00130 // set it up 00131 int DSS = bits - 1; // DSS (data select size) 00132 int SPO = (polarity) ? 1 : 0; // SPO - clock out polarity 00133 int SPH = (phase) ? 1 : 0; // SPH - clock out phase 00134 00135 int FRF = 0; // FRF (frame format) = SPI 00136 uint32_t tmp = obj->spi->CR0; 00137 tmp &= ~(0xFFFF); 00138 tmp |= DSS << 0 00139 | FRF << 4 00140 | SPO << 6 00141 | SPH << 7; 00142 obj->spi->CR0 = tmp; 00143 00144 tmp = obj->spi->CR1; 00145 tmp &= ~(0xD); 00146 tmp |= 0 << 0 // LBM - loop back mode - off 00147 | ((slave) ? 1 : 0) << 2 // MS - master slave mode, 1 = slave 00148 | 0 << 3; // SOD - slave output disable - na 00149 obj->spi->CR1 = tmp; 00150 ssp_enable(obj); 00151 } 00152 00153 void spi_frequency(spi_t *obj, int hz) { 00154 ssp_disable(obj); 00155 00156 uint32_t PCLK = PeripheralClock ; 00157 00158 int prescaler; 00159 00160 for (prescaler = 2; prescaler <= 254; prescaler += 2) { 00161 int prescale_hz = PCLK / prescaler; 00162 00163 // calculate the divider 00164 int divider = floor(((float)prescale_hz / (float)hz) + 0.5f); 00165 00166 // check we can support the divider 00167 if (divider < 256) { 00168 // prescaler 00169 obj->spi->CPSR = prescaler; 00170 00171 // divider 00172 obj->spi->CR0 &= ~(0xFFFF << 8); 00173 obj->spi->CR0 |= (divider - 1) << 8; 00174 ssp_enable(obj); 00175 return; 00176 } 00177 } 00178 error("Couldn't setup requested SPI frequency"); 00179 } 00180 00181 static inline int ssp_disable(spi_t *obj) { 00182 return obj->spi->CR1 &= ~(1 << 1); 00183 } 00184 00185 static inline int ssp_enable(spi_t *obj) { 00186 return obj->spi->CR1 |= (1 << 1); 00187 } 00188 00189 static inline int ssp_readable(spi_t *obj) { 00190 return obj->spi->SR & (1 << 2); 00191 } 00192 00193 static inline int ssp_writeable(spi_t *obj) { 00194 return obj->spi->SR & (1 << 1); 00195 } 00196 00197 static inline void ssp_write(spi_t *obj, int value) { 00198 while (!ssp_writeable(obj)); 00199 obj->spi->DR = value; 00200 } 00201 00202 static inline int ssp_read(spi_t *obj) { 00203 while (!ssp_readable(obj)); 00204 return obj->spi->DR; 00205 } 00206 00207 static inline int ssp_busy(spi_t *obj) { 00208 return (obj->spi->SR & (1 << 4)) ? (1) : (0); 00209 } 00210 00211 int spi_master_write(spi_t *obj, int value) { 00212 ssp_write(obj, value); 00213 return ssp_read(obj); 00214 } 00215 00216 int spi_slave_receive(spi_t *obj) { 00217 return (ssp_readable(obj) && !ssp_busy(obj)) ? (1) : (0); 00218 }; 00219 00220 int spi_slave_read(spi_t *obj) { 00221 return obj->spi->DR; 00222 } 00223 00224 void spi_slave_write(spi_t *obj, int value) { 00225 while (ssp_writeable(obj) == 0) ; 00226 obj->spi->DR = value; 00227 } 00228 00229 int spi_busy(spi_t *obj) { 00230 return ssp_busy(obj); 00231 }
Generated on Tue Jul 12 2022 13:47:02 by
1.7.2
