source: EcnlProtoTool/trunk/asp3_dcre/mbed/targets/hal/TARGET_RENESAS/TARGET_RZ_A1H/spi_api.c@ 270

Last change on this file since 270 was 270, checked in by coas-nagasima, 7 years ago

mruby版ECNLプロトタイピング・ツールを追加

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
  • Property svn:mime-type set to text/x-csrc
File size: 6.9 KB
Line 
1/* mbed Microcontroller Library
2 * Copyright (c) 2006-2013 ARM Limited
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16#include "mbed_assert.h"
17#include <math.h>
18
19#include "spi_api.h"
20#include "cmsis.h"
21#include "pinmap.h"
22#include "mbed_error.h"
23#include "RZ_A1_Init.h"
24
25static const PinMap PinMap_SPI_SCLK[] = {
26 {P10_12, SPI_0, 4},
27 {P4_4 , SPI_1, 2},
28 {P11_12, SPI_1, 2},
29 {P8_3 , SPI_2, 3},
30 {NC , NC , 0}
31};
32
33static const PinMap PinMap_SPI_SSEL[] = {
34 {P10_13, SPI_0, 4},
35 {P4_5 , SPI_1, 2},
36 {P11_13, SPI_1, 2},
37 {P8_4 , SPI_2, 3},
38 {NC , NC , 0}
39};
40
41static const PinMap PinMap_SPI_MOSI[] = {
42 {P10_14, SPI_0, 4},
43 {P4_6 , SPI_1, 2},
44 {P11_14, SPI_1, 2},
45 {P8_5 , SPI_2, 3},
46 {NC , NC , 0}
47};
48
49static const PinMap PinMap_SPI_MISO[] = {
50 {P10_15, SPI_0, 4},
51 {P4_7 , SPI_1, 2},
52 {P11_15, SPI_1, 2},
53 {P8_6 , SPI_2, 3},
54 {NC , NC , 0}
55};
56
57static const struct st_rspi *RSPI[] = RSPI_ADDRESS_LIST;
58
59static inline void spi_disable(spi_t *obj);
60static inline void spi_enable(spi_t *obj);
61static inline int spi_readable(spi_t *obj);
62static inline void spi_write(spi_t *obj, int value);
63static inline int spi_read(spi_t *obj);
64
65void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel) {
66 // determine the SPI to use
67 volatile uint8_t dummy;
68 uint32_t spi_mosi = pinmap_peripheral(mosi, PinMap_SPI_MOSI);
69 uint32_t spi_miso = pinmap_peripheral(miso, PinMap_SPI_MISO);
70 uint32_t spi_sclk = pinmap_peripheral(sclk, PinMap_SPI_SCLK);
71 uint32_t spi_ssel = pinmap_peripheral(ssel, PinMap_SPI_SSEL);
72 uint32_t spi_data = pinmap_merge(spi_mosi, spi_miso);
73 uint32_t spi_cntl = pinmap_merge(spi_sclk, spi_ssel);
74 uint32_t spi = pinmap_merge(spi_data, spi_cntl);
75
76 MBED_ASSERT((int)spi != NC);
77
78 obj->spi = (struct st_rspi *)RSPI[spi];
79
80 // enable power and clocking
81 switch (spi) {
82 case SPI_0: CPGSTBCR10 &= ~(0x80); break;
83 case SPI_1: CPGSTBCR10 &= ~(0x40); break;
84 case SPI_2: CPGSTBCR10 &= ~(0x20); break;
85 }
86 dummy = CPGSTBCR10;
87
88 obj->spi->SPCR = 0x00; // CTRL to 0
89 obj->spi->SPSCR = 0x00; // no sequential operation
90 obj->spi->SSLP = 0x00; // SSL 'L' active
91 obj->spi->SPDCR = 0x20; // byte access
92 obj->spi->SPCKD = 0x00; // SSL -> enable CLK delay : 1RSPCK
93 obj->spi->SSLND = 0x00; // CLK end -> SSL neg delay : 1RSPCK
94 obj->spi->SPND = 0x00; // delay between CMD : 1RSPCK + 2P1CLK
95 obj->spi->SPPCR = 0x20; // MOSI Idle fixed value equals 0
96 obj->spi->SPBFCR = 0xf0; // and set trigger count: read 1, write 1
97 obj->spi->SPBFCR = 0x30; // and reset buffer
98
99 // pin out the spi pins
100 pinmap_pinout(mosi, PinMap_SPI_MOSI);
101 pinmap_pinout(miso, PinMap_SPI_MISO);
102 pinmap_pinout(sclk, PinMap_SPI_SCLK);
103 if ((int)ssel != NC) {
104 pinmap_pinout(ssel, PinMap_SPI_SSEL);
105 }
106}
107
108void spi_free(spi_t *obj) {}
109
110void spi_format(spi_t *obj, int bits, int mode, int slave) {
111 int DSS; // DSS (data select size)
112 int polarity = (mode & 0x2) ? 1 : 0;
113 int phase = (mode & 0x1) ? 1 : 0;
114 uint16_t tmp = 0;
115 uint16_t mask = 0xf03;
116 uint16_t wk_spcmd0;
117 uint8_t splw;
118
119 switch (mode) {
120 case 0:
121 case 1:
122 case 2:
123 case 3:
124 // Do Nothing
125 break;
126 default:
127 error("SPI format error");
128 return;
129 }
130
131 switch (bits) {
132 case 8:
133 DSS = 0x7;
134 splw = 0x20;
135 break;
136 case 16:
137 DSS = 0xf;
138 splw = 0x40;
139 break;
140 case 32:
141 DSS = 0x2;
142 splw = 0x60;
143 break;
144 default:
145 error("SPI module don't support other than 8/16/32bits");
146 return;
147 }
148 tmp |= phase;
149 tmp |= (polarity << 1);
150 tmp |= (DSS << 8);
151 obj->bits = bits;
152
153 spi_disable(obj);
154 wk_spcmd0 = obj->spi->SPCMD0;
155 wk_spcmd0 &= ~mask;
156 wk_spcmd0 |= (mask & tmp);
157 obj->spi->SPCMD0 = wk_spcmd0;
158 obj->spi->SPDCR = splw;
159 if (slave) {
160 obj->spi->SPCR &=~(1 << 3); // MSTR to 0
161 } else {
162 obj->spi->SPCR |= (1 << 3); // MSTR to 1
163 }
164 spi_enable(obj);
165}
166
167void spi_frequency(spi_t *obj, int hz) {
168 uint32_t pclk_base;
169 uint32_t div;
170 uint32_t brdv = 0;
171 uint32_t hz_max;
172 uint32_t hz_min;
173 uint16_t mask = 0x000c;
174 uint16_t wk_spcmd0;
175
176 /* set PCLK */
177 if (RZ_A1_IsClockMode0() == false) {
178 pclk_base = CM1_RENESAS_RZ_A1_P1_CLK;
179 } else {
180 pclk_base = CM0_RENESAS_RZ_A1_P1_CLK;
181 }
182
183 hz_min = pclk_base / 2 / 256 / 8;
184 hz_max = pclk_base / 2;
185 if ((hz < hz_min) || (hz > hz_max)) {
186 error("Couldn't setup requested SPI frequency");
187 return;
188 }
189
190 div = (pclk_base / hz / 2);
191 while (div > 256) {
192 div >>= 1;
193 brdv++;
194 }
195 div -= 1;
196 brdv = (brdv << 2);
197
198 spi_disable(obj);
199 obj->spi->SPBR = div;
200 wk_spcmd0 = obj->spi->SPCMD0;
201 wk_spcmd0 &= ~mask;
202 wk_spcmd0 |= (mask & brdv);
203 obj->spi->SPCMD0 = wk_spcmd0;
204 spi_enable(obj);
205}
206
207static inline void spi_disable(spi_t *obj) {
208 obj->spi->SPCR &= ~(1 << 6); // SPE to 0
209}
210
211static inline void spi_enable(spi_t *obj) {
212 obj->spi->SPCR |= (1 << 6); // SPE to 1
213}
214
215static inline int spi_readable(spi_t *obj) {
216 return obj->spi->SPSR & (1 << 7); // SPRF
217}
218
219static inline int spi_tend(spi_t *obj) {
220 return obj->spi->SPSR & (1 << 6); // TEND
221}
222
223static inline void spi_write(spi_t *obj, int value) {
224 if (obj->bits == 8) {
225 obj->spi->SPDR.UINT8[0] = (uint8_t)value;
226 } else if (obj->bits == 16) {
227 obj->spi->SPDR.UINT16[0] = (uint16_t)value;
228 } else {
229 obj->spi->SPDR.UINT32 = (uint32_t)value;
230 }
231}
232
233static inline int spi_read(spi_t *obj) {
234 int read_data;
235
236 if (obj->bits == 8) {
237 read_data = obj->spi->SPDR.UINT8[0];
238 } else if (obj->bits == 16) {
239 read_data = obj->spi->SPDR.UINT16[0];
240 } else {
241 read_data = obj->spi->SPDR.UINT32;
242 }
243
244 return read_data;
245}
246
247int spi_master_write(spi_t *obj, int value) {
248 spi_write(obj, value);
249 while(!spi_tend(obj));
250 return spi_read(obj);
251}
252
253int spi_slave_receive(spi_t *obj) {
254 return (spi_readable(obj) && !spi_busy(obj)) ? (1) : (0);
255}
256
257int spi_slave_read(spi_t *obj) {
258 return spi_read(obj);
259}
260
261void spi_slave_write(spi_t *obj, int value) {
262 spi_write(obj, value);
263}
264
265int spi_busy(spi_t *obj) {
266 return 0;
267}
Note: See TracBrowser for help on using the repository browser.