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