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 "spi_api.h" 00017 00018 #include <math.h> 00019 00020 #include "cmsis.h" 00021 #include "pinmap.h" 00022 #include "error.h" 00023 00024 static const PinMap PinMap_SPI_SCLK[] = { 00025 {PTE2, SPI_1, 2}, 00026 {PTC5, SPI_0, 2}, 00027 {PTD1, SPI_0, 2}, 00028 {NC , NC , 0} 00029 }; 00030 00031 static const PinMap PinMap_SPI_MOSI[] = { 00032 {PTE1, SPI_1, 2}, 00033 {PTC6, SPI_0, 2}, 00034 {PTD2, SPI_0, 2}, 00035 {NC , NC , 0} 00036 }; 00037 00038 static const PinMap PinMap_SPI_MISO[] = { 00039 {PTE3, SPI_1, 2}, 00040 {PTC7, SPI_0, 2}, 00041 {PTD3, SPI_0, 2}, 00042 {NC , NC , 0} 00043 }; 00044 00045 static const PinMap PinMap_SPI_SSEL[] = { 00046 {PTE4, SPI_1, 2}, 00047 {PTC4, SPI_0, 2}, 00048 {PTD0, SPI_0, 2}, 00049 {NC , NC , 0} 00050 }; 00051 00052 void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel) { 00053 // determine the SPI to use 00054 SPIName spi_mosi = (SPIName)pinmap_peripheral(mosi, PinMap_SPI_MOSI); 00055 SPIName spi_miso = (SPIName)pinmap_peripheral(miso, PinMap_SPI_MISO); 00056 SPIName spi_sclk = (SPIName)pinmap_peripheral(sclk, PinMap_SPI_SCLK); 00057 SPIName spi_ssel = (SPIName)pinmap_peripheral(ssel, PinMap_SPI_SSEL); 00058 SPIName spi_data = (SPIName)pinmap_merge(spi_mosi, spi_miso); 00059 SPIName spi_cntl = (SPIName)pinmap_merge(spi_sclk, spi_ssel); 00060 00061 obj->spi = (SPI_Type*)pinmap_merge(spi_data, spi_cntl); 00062 if ((int)obj->spi == NC) { 00063 error("SPI pinout mapping failed"); 00064 } 00065 00066 // enable power and clocking 00067 switch ((int)obj->spi) { 00068 case SPI_0: SIM->SCGC5 |= 1 << 11; SIM->SCGC4 |= 1 << 22; break; 00069 case SPI_1: SIM->SCGC5 |= 1 << 13; SIM->SCGC4 |= 1 << 23; break; 00070 } 00071 00072 // set default format and frequency 00073 if (ssel == NC) { 00074 spi_format(obj, 8, 0, 0); // 8 bits, mode 0, master 00075 } else { 00076 spi_format(obj, 8, 0, 1); // 8 bits, mode 0, slave 00077 } 00078 spi_frequency(obj, 1000000); 00079 00080 // enable SPI 00081 obj->spi->C1 |= SPI_C1_SPE_MASK; 00082 00083 // pin out the spi pins 00084 pinmap_pinout(mosi, PinMap_SPI_MOSI); 00085 pinmap_pinout(miso, PinMap_SPI_MISO); 00086 pinmap_pinout(sclk, PinMap_SPI_SCLK); 00087 if (ssel != NC) { 00088 pinmap_pinout(ssel, PinMap_SPI_SSEL); 00089 } 00090 } 00091 00092 void spi_free(spi_t *obj) { 00093 // [TODO] 00094 } 00095 void spi_format(spi_t *obj, int bits, int mode, int slave) { 00096 if (bits != 8) { 00097 error("Only 8bits SPI supported"); 00098 } 00099 00100 if ((mode < 0) || (mode > 3)) { 00101 error("SPI mode unsupported"); 00102 } 00103 00104 uint8_t polarity = (mode & 0x2) ? 1 : 0; 00105 uint8_t phase = (mode & 0x1) ? 1 : 0; 00106 uint8_t c1_data = ((!slave) << 4) | (polarity << 3) | (phase << 2); 00107 00108 // clear MSTR, CPOL and CPHA bits 00109 obj->spi->C1 &= ~(0x7 << 2); 00110 00111 // write new value 00112 obj->spi->C1 |= c1_data; 00113 } 00114 00115 void spi_frequency(spi_t *obj, int hz) { 00116 uint32_t error = 0; 00117 uint32_t p_error = 0xffffffff; 00118 uint32_t ref = 0; 00119 uint8_t spr = 0; 00120 uint8_t ref_spr = 0; 00121 uint8_t ref_prescaler = 0; 00122 00123 // bus clk 00124 uint32_t PCLK = 48000000u; 00125 uint8_t prescaler = 1; 00126 uint8_t divisor = 2; 00127 00128 for (prescaler = 1; prescaler <= 8; prescaler++) { 00129 divisor = 2; 00130 for (spr = 0; spr <= 8; spr++) { 00131 ref = PCLK / (prescaler*divisor); 00132 error = (ref > hz) ? ref - hz : hz - ref; 00133 if (error < p_error) { 00134 ref_spr = spr; 00135 ref_prescaler = prescaler - 1; 00136 p_error = error; 00137 } 00138 divisor *= 2; 00139 } 00140 } 00141 00142 // set SPPR and SPR 00143 obj->spi->BR = ((ref_prescaler & 0x7) << 4) | (ref_spr & 0xf); 00144 } 00145 00146 static inline int spi_writeable(spi_t * obj) { 00147 return (obj->spi->S & SPI_S_SPTEF_MASK) ? 1 : 0; 00148 } 00149 00150 static inline int spi_readable(spi_t * obj) { 00151 return (obj->spi->S & SPI_S_SPRF_MASK) ? 1 : 0; 00152 } 00153 00154 int spi_master_write(spi_t *obj, int value) { 00155 // wait tx buffer empty 00156 while(!spi_writeable(obj)); 00157 obj->spi->D = (value & 0xff); 00158 00159 // wait rx buffer full 00160 while (!spi_readable(obj)); 00161 return obj->spi->D & 0xff; 00162 } 00163 00164 int spi_slave_receive(spi_t *obj) { 00165 return spi_readable(obj); 00166 } 00167 00168 int spi_slave_read(spi_t *obj) { 00169 return obj->spi->D; 00170 } 00171 00172 void spi_slave_write(spi_t *obj, int value) { 00173 while (!spi_writeable(obj)); 00174 obj->spi->D = value; 00175 }
Generated on Tue Jul 12 2022 13:47:02 by
1.7.2
