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 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