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