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_20, SPI_0, 3}, 00027 {P1_31, SPI_1, 2}, 00028 {NC , NC , 0} 00029 }; 00030 00031 static const PinMap PinMap_SPI_MOSI[] = { 00032 {P0_9 , SPI_1, 2}, 00033 {P0_13, SPI_1, 2}, 00034 {P0_18, SPI_0, 2}, 00035 {P1_24, SPI_0, 3}, 00036 {NC , NC , 0} 00037 }; 00038 00039 static const PinMap PinMap_SPI_MISO[] = { 00040 {P0_8 , SPI_1, 2}, 00041 {P0_12, SPI_1, 2}, 00042 {P0_17, SPI_0, 2}, 00043 {P1_23, SPI_0, 3}, 00044 {NC , NC , 0} 00045 }; 00046 00047 static const PinMap PinMap_SPI_SSEL[] = { 00048 {P0_6 , SPI_1, 2}, 00049 {P0_11, SPI_1, 2}, 00050 {P0_16, SPI_0, 2}, 00051 {P1_21, SPI_0, 3}, 00052 {NC , NC , 0} 00053 }; 00054 00055 static inline int ssp_disable(spi_t *obj); 00056 static inline int ssp_enable(spi_t *obj); 00057 00058 void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel) { 00059 // determine the SPI to use 00060 SPIName spi_mosi = (SPIName)pinmap_peripheral(mosi, PinMap_SPI_MOSI); 00061 SPIName spi_miso = (SPIName)pinmap_peripheral(miso, PinMap_SPI_MISO); 00062 SPIName spi_sclk = (SPIName)pinmap_peripheral(sclk, PinMap_SPI_SCLK); 00063 SPIName spi_ssel = (SPIName)pinmap_peripheral(ssel, PinMap_SPI_SSEL); 00064 SPIName spi_data = (SPIName)pinmap_merge(spi_mosi, spi_miso); 00065 SPIName spi_cntl = (SPIName)pinmap_merge(spi_sclk, spi_ssel); 00066 obj->spi = (LPC_SSP_TypeDef*)pinmap_merge(spi_data, spi_cntl); 00067 if ((int)obj->spi == NC) { 00068 error("SPI pinout mapping failed"); 00069 } 00070 00071 // enable power and clocking 00072 switch ((int)obj->spi) { 00073 case SPI_0: LPC_SC->PCONP |= 1 << 21; break; 00074 case SPI_1: LPC_SC->PCONP |= 1 << 10; break; 00075 } 00076 00077 // set default format and frequency 00078 if (ssel == NC) { 00079 spi_format(obj, 8, 0, 0); // 8 bits, mode 0, master 00080 } else { 00081 spi_format(obj, 8, 0, 1); // 8 bits, mode 0, slave 00082 } 00083 spi_frequency(obj, 1000000); 00084 00085 // enable the ssp channel 00086 ssp_enable(obj); 00087 00088 // pin out the spi pins 00089 pinmap_pinout(mosi, PinMap_SPI_MOSI); 00090 pinmap_pinout(miso, PinMap_SPI_MISO); 00091 pinmap_pinout(sclk, PinMap_SPI_SCLK); 00092 if (ssel != NC) { 00093 pinmap_pinout(ssel, PinMap_SPI_SSEL); 00094 } 00095 } 00096 00097 void spi_free(spi_t *obj) {} 00098 00099 void spi_format(spi_t *obj, int bits, int mode, int slave) { 00100 ssp_disable(obj); 00101 if (!(bits >= 4 && bits <= 16) || !(mode >= 0 && mode <= 3)) { 00102 error("SPI format error"); 00103 } 00104 00105 int polarity = (mode & 0x2) ? 1 : 0; 00106 int phase = (mode & 0x1) ? 1 : 0; 00107 00108 // set it up 00109 int DSS = bits - 1; // DSS (data select size) 00110 int SPO = (polarity) ? 1 : 0; // SPO - clock out polarity 00111 int SPH = (phase) ? 1 : 0; // SPH - clock out phase 00112 00113 int FRF = 0; // FRF (frame format) = SPI 00114 uint32_t tmp = obj->spi->CR0; 00115 tmp &= ~(0xFFFF); 00116 tmp |= DSS << 0 00117 | FRF << 4 00118 | SPO << 6 00119 | SPH << 7; 00120 obj->spi->CR0 = tmp; 00121 00122 tmp = obj->spi->CR1; 00123 tmp &= ~(0xD); 00124 tmp |= 0 << 0 // LBM - loop back mode - off 00125 | ((slave) ? 1 : 0) << 2 // MS - master slave mode, 1 = slave 00126 | 0 << 3; // SOD - slave output disable - na 00127 obj->spi->CR1 = tmp; 00128 00129 ssp_enable(obj); 00130 } 00131 00132 void spi_frequency(spi_t *obj, int hz) { 00133 ssp_disable(obj); 00134 00135 // setup the spi clock diveder to /1 00136 switch ((int)obj->spi) { 00137 case SPI_0: 00138 LPC_SC->PCLKSEL1 &= ~(3 << 10); 00139 LPC_SC->PCLKSEL1 |= (1 << 10); 00140 break; 00141 case SPI_1: 00142 LPC_SC->PCLKSEL0 &= ~(3 << 20); 00143 LPC_SC->PCLKSEL0 |= (1 << 20); 00144 break; 00145 } 00146 00147 uint32_t PCLK = SystemCoreClock; 00148 00149 int prescaler; 00150 00151 for (prescaler = 2; prescaler <= 254; prescaler += 2) { 00152 int prescale_hz = PCLK / prescaler; 00153 00154 // calculate the divider 00155 int divider = floor(((float)prescale_hz / (float)hz) + 0.5f); 00156 00157 // check we can support the divider 00158 if (divider < 256) { 00159 // prescaler 00160 obj->spi->CPSR = prescaler; 00161 00162 // divider 00163 obj->spi->CR0 &= ~(0xFFFF << 8); 00164 obj->spi->CR0 |= (divider - 1) << 8; 00165 ssp_enable(obj); 00166 return; 00167 } 00168 } 00169 error("Couldn't setup requested SPI frequency"); 00170 } 00171 00172 static inline int ssp_disable(spi_t *obj) { 00173 return obj->spi->CR1 &= ~(1 << 1); 00174 } 00175 00176 static inline int ssp_enable(spi_t *obj) { 00177 return obj->spi->CR1 |= (1 << 1); 00178 } 00179 00180 static inline int ssp_readable(spi_t *obj) { 00181 return obj->spi->SR & (1 << 2); 00182 } 00183 00184 static inline int ssp_writeable(spi_t *obj) { 00185 return obj->spi->SR & (1 << 1); 00186 } 00187 00188 static inline void ssp_write(spi_t *obj, int value) { 00189 while (!ssp_writeable(obj)); 00190 obj->spi->DR = value; 00191 } 00192 00193 static inline int ssp_read(spi_t *obj) { 00194 while (!ssp_readable(obj)); 00195 return obj->spi->DR; 00196 } 00197 00198 static inline int ssp_busy(spi_t *obj) { 00199 return (obj->spi->SR & (1 << 4)) ? (1) : (0); 00200 } 00201 00202 int spi_master_write(spi_t *obj, int value) { 00203 ssp_write(obj, value); 00204 return ssp_read(obj); 00205 } 00206 00207 int spi_slave_receive(spi_t *obj) { 00208 return (ssp_readable(obj) && !ssp_busy(obj)) ? (1) : (0); 00209 }; 00210 00211 int spi_slave_read(spi_t *obj) { 00212 return obj->spi->DR; 00213 } 00214 00215 void spi_slave_write(spi_t *obj, int value) { 00216 while (ssp_writeable(obj) == 0) ; 00217 obj->spi->DR = value; 00218 } 00219 00220 int spi_busy(spi_t *obj) { 00221 return ssp_busy(obj); 00222 }
Generated on Tue Jul 12 2022 13:47:02 by
1.7.2
