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 SWM_Map SWM_SPI_SSEL[] = { 00024 {4, 16}, 00025 {5, 16}, 00026 }; 00027 00028 static const SWM_Map SWM_SPI_SCLK[] = { 00029 {3, 24}, 00030 {4, 24}, 00031 }; 00032 00033 static const SWM_Map SWM_SPI_MOSI[] = { 00034 {4, 0}, 00035 {5, 0}, 00036 }; 00037 00038 static const SWM_Map SWM_SPI_MISO[] = { 00039 {4, 8}, 00040 {5, 16}, 00041 }; 00042 00043 // bit flags for used SPIs 00044 static unsigned char spi_used = 0; 00045 static int get_available_spi(void) { 00046 int i; 00047 for (i=0; i<2; i++) { 00048 if ((spi_used & (1 << i)) == 0) 00049 return i; 00050 } 00051 return -1; 00052 } 00053 00054 static inline int ssp_disable(spi_t *obj); 00055 static inline int ssp_enable(spi_t *obj); 00056 00057 void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel) { 00058 int spi_n = get_available_spi(); 00059 if (spi_n == -1) { 00060 error("No available SPI"); 00061 } 00062 obj->spi_n = spi_n; 00063 spi_used |= (1 << spi_n); 00064 00065 obj->spi = (spi_n) ? (LPC_SPI_TypeDef *)(LPC_SPI1_BASE) : (LPC_SPI_TypeDef *)(LPC_SPI0_BASE); 00066 00067 const SWM_Map *swm; 00068 uint32_t regVal; 00069 00070 swm = &SWM_SPI_SCLK[obj->spi_n]; 00071 regVal = LPC_SWM->PINASSIGN[swm->n] & ~(0xFF << swm->offset); 00072 LPC_SWM->PINASSIGN[swm->n] = regVal | (sclk << swm->offset); 00073 00074 swm = &SWM_SPI_MOSI[obj->spi_n]; 00075 regVal = LPC_SWM->PINASSIGN[swm->n] & ~(0xFF << swm->offset); 00076 LPC_SWM->PINASSIGN[swm->n] = regVal | (mosi << swm->offset); 00077 00078 swm = &SWM_SPI_MISO[obj->spi_n]; 00079 regVal = LPC_SWM->PINASSIGN[swm->n] & ~(0xFF << swm->offset); 00080 LPC_SWM->PINASSIGN[swm->n] = regVal | (miso << swm->offset); 00081 00082 swm = &SWM_SPI_SSEL[obj->spi_n]; 00083 regVal = LPC_SWM->PINASSIGN[swm->n] & ~(0xFF << swm->offset); 00084 LPC_SWM->PINASSIGN[swm->n] = regVal | (ssel << swm->offset); 00085 00086 // clear interrupts 00087 obj->spi->INTENCLR = 0x3f; 00088 00089 // enable power and clocking 00090 switch (obj->spi_n) { 00091 case 0: 00092 LPC_SYSCON->SYSAHBCLKCTRL |= (1<<11); 00093 LPC_SYSCON->PRESETCTRL &= ~(0x1<<0); 00094 LPC_SYSCON->PRESETCTRL |= (0x1<<0); 00095 break; 00096 case 1: 00097 LPC_SYSCON->SYSAHBCLKCTRL |= (1<<12); 00098 LPC_SYSCON->PRESETCTRL &= ~(0x1<<1); 00099 LPC_SYSCON->PRESETCTRL |= (0x1<<1); 00100 break; 00101 } 00102 00103 // set default format and frequency 00104 if (ssel == NC) { 00105 spi_format(obj, 8, 0, 0); // 8 bits, mode 0, master 00106 } else { 00107 spi_format(obj, 8, 0, 1); // 8 bits, mode 0, slave 00108 } 00109 spi_frequency(obj, 1000000); 00110 00111 // enable the ssp channel 00112 ssp_enable(obj); 00113 } 00114 00115 void spi_free(spi_t *obj) {} 00116 00117 void spi_format(spi_t *obj, int bits, int mode, int slave) { 00118 ssp_disable(obj); 00119 00120 if (!(bits >= 1 && bits <= 16) || !(mode >= 0 && mode <= 3)) { 00121 error("SPI format error"); 00122 } 00123 00124 00125 int polarity = (mode & 0x2) ? 1 : 0; 00126 int phase = (mode & 0x1) ? 1 : 0; 00127 00128 // set it up 00129 int DSS = bits - 1; // DSS (data select size) 00130 int SPO = (polarity) ? 1 : 0; // SPO - clock out polarity 00131 int SPH = (phase) ? 1 : 0; // SPH - clock out phase 00132 00133 uint32_t tmp = obj->spi->CFG; 00134 tmp &= ~((1 << 2) | (1 << 4) | (1 << 5)); 00135 tmp |= (SPH << 4) | (SPO << 5) | ((slave ? 0 : 1) << 2); 00136 obj->spi->CFG = tmp; 00137 00138 // select frame length 00139 tmp = obj->spi->TXDATCTL; 00140 tmp &= ~(0xf << 24); 00141 tmp |= (DSS << 24); 00142 obj->spi->TXDATCTL = tmp; 00143 00144 ssp_enable(obj); 00145 } 00146 00147 void spi_frequency(spi_t *obj, int hz) { 00148 ssp_disable(obj); 00149 00150 uint32_t PCLK = SystemCoreClock; 00151 00152 obj->spi->DIV = PCLK/hz - 1; 00153 obj->spi->DLY = 0; 00154 ssp_enable(obj); 00155 } 00156 00157 static inline int ssp_disable(spi_t *obj) { 00158 return obj->spi->CFG &= ~(1 << 0); 00159 } 00160 00161 static inline int ssp_enable(spi_t *obj) { 00162 return obj->spi->CFG |= (1 << 0); 00163 } 00164 00165 static inline int ssp_readable(spi_t *obj) { 00166 return obj->spi->STAT & (1 << 0); 00167 } 00168 00169 static inline int ssp_writeable(spi_t *obj) { 00170 return obj->spi->STAT & (1 << 1); 00171 } 00172 00173 static inline void ssp_write(spi_t *obj, int value) { 00174 while (!ssp_writeable(obj)); 00175 // end of transfer 00176 obj->spi->TXDATCTL |= (1 << 20); 00177 obj->spi->TXDAT = value; 00178 } 00179 00180 static inline int ssp_read(spi_t *obj) { 00181 while (!ssp_readable(obj)); 00182 return obj->spi->RXDAT; 00183 } 00184 00185 static inline int ssp_busy(spi_t *obj) { 00186 // TODO 00187 return 0; 00188 } 00189 00190 int spi_master_write(spi_t *obj, int value) { 00191 ssp_write(obj, value); 00192 return ssp_read(obj); 00193 } 00194 00195 int spi_slave_receive(spi_t *obj) { 00196 return (ssp_readable(obj) && !ssp_busy(obj)) ? (1) : (0); 00197 }; 00198 00199 int spi_slave_read(spi_t *obj) { 00200 return obj->spi->RXDAT; 00201 } 00202 00203 void spi_slave_write(spi_t *obj, int value) { 00204 while (ssp_writeable(obj) == 0) ; 00205 obj->spi->TXDAT = value; 00206 } 00207 00208 int spi_busy(spi_t *obj) { 00209 return ssp_busy(obj); 00210 }
Generated on Tue Jul 12 2022 13:47:02 by 1.7.2