fix for mbed lib issue 3 (i2c problem) see also https://mbed.org/users/mbed_official/code/mbed/issues/3 affected implementations: LPC812, LPC11U24, LPC1768, LPC2368, LPC4088
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