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