source: asp3_tinet_ecnl_arm/trunk/asp3_dcre/mbed/targets/TARGET_RENESAS/TARGET_RZ_A1H/spi_api.c@ 352

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

arm向けASP3版ECNLを追加

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc;charset=UTF-8
File size: 15.6 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 {P6_4 , SPI_1, 7},
29 {P11_12, SPI_1, 2},
30 {P8_3 , SPI_2, 3},
31 {P5_0 , SPI_3, 8},
32 {NC , NC , 0}
33};
34
35static const PinMap PinMap_SPI_SSEL[] = {
36 {P10_13, SPI_0, 4},
37 {P4_5 , SPI_1, 2},
38 {P6_5 , SPI_1, 7},
39 {P11_13, SPI_1, 2},
40 {P8_4 , SPI_2, 3},
41 {P5_1 , SPI_3, 8},
42 {NC , NC , 0}
43};
44
45static const PinMap PinMap_SPI_MOSI[] = {
46 {P10_14, SPI_0, 4},
47 {P4_6 , SPI_1, 2},
48 {P6_6 , SPI_1, 7},
49 {P11_14, SPI_1, 2},
50 {P8_5 , SPI_2, 3},
51 {P5_2 , SPI_3, 8},
52 {NC , NC , 0}
53};
54
55static const PinMap PinMap_SPI_MISO[] = {
56 {P10_15, SPI_0, 4},
57 {P4_7 , SPI_1, 2},
58 {P6_7 , SPI_1, 7},
59 {P11_15, SPI_1, 2},
60 {P8_6 , SPI_2, 3},
61 {P5_3 , SPI_3, 8},
62 {NC , NC , 0}
63};
64
65static const struct st_rspi *RSPI[] = RSPI_ADDRESS_LIST;
66
67static inline void spi_disable(spi_t *obj);
68static inline void spi_enable(spi_t *obj);
69static inline int spi_readable(spi_t *obj);
70static inline void spi_write(spi_t *obj, int value);
71static inline int spi_read(spi_t *obj);
72
73void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel) {
74 // determine the SPI to use
75 volatile uint8_t dummy;
76 uint32_t spi_mosi = pinmap_peripheral(mosi, PinMap_SPI_MOSI);
77 uint32_t spi_miso = pinmap_peripheral(miso, PinMap_SPI_MISO);
78 uint32_t spi_sclk = pinmap_peripheral(sclk, PinMap_SPI_SCLK);
79 uint32_t spi_ssel = pinmap_peripheral(ssel, PinMap_SPI_SSEL);
80 uint32_t spi_data = pinmap_merge(spi_mosi, spi_miso);
81 uint32_t spi_cntl = pinmap_merge(spi_sclk, spi_ssel);
82 uint32_t spi = pinmap_merge(spi_data, spi_cntl);
83
84 MBED_ASSERT((int)spi != NC);
85
86 obj->spi.spi = (struct st_rspi *)RSPI[spi];
87 obj->spi.index = spi;
88
89 // enable power and clocking
90 switch (spi) {
91 case SPI_0: CPGSTBCR10 &= ~(0x80); break;
92 case SPI_1: CPGSTBCR10 &= ~(0x40); break;
93 case SPI_2: CPGSTBCR10 &= ~(0x20); break;
94 case SPI_3: CPGSTBCR10 &= ~(0x10); break;
95 }
96 dummy = CPGSTBCR10;
97
98 obj->spi.spi->SPCR = 0x00; // CTRL to 0
99 obj->spi.spi->SPSCR = 0x00; // no sequential operation
100 obj->spi.spi->SSLP = 0x00; // SSL 'L' active
101 obj->spi.spi->SPDCR = 0x20; // byte access
102 obj->spi.spi->SPCKD = 0x00; // SSL -> enable CLK delay : 1RSPCK
103 obj->spi.spi->SSLND = 0x00; // CLK end -> SSL neg delay : 1RSPCK
104 obj->spi.spi->SPND = 0x00; // delay between CMD : 1RSPCK + 2P1CLK
105 obj->spi.spi->SPPCR = 0x20; // MOSI Idle fixed value equals 0
106 obj->spi.spi->SPBFCR = 0xf0; // and set trigger count: read 1, write 1
107 obj->spi.spi->SPBFCR = 0x30; // and reset buffer
108
109 // pin out the spi pins
110 pinmap_pinout(mosi, PinMap_SPI_MOSI);
111 pinmap_pinout(miso, PinMap_SPI_MISO);
112 pinmap_pinout(sclk, PinMap_SPI_SCLK);
113 if ((int)ssel != NC) {
114 pinmap_pinout(ssel, PinMap_SPI_SSEL);
115 }
116}
117
118void spi_free(spi_t *obj) {}
119
120void spi_format(spi_t *obj, int bits, int mode, int slave) {
121 int DSS; // DSS (data select size)
122 int polarity = (mode & 0x2) ? 1 : 0;
123 int phase = (mode & 0x1) ? 1 : 0;
124 uint16_t tmp = 0;
125 uint16_t mask = 0xf03;
126 uint16_t wk_spcmd0;
127 uint8_t splw;
128
129 switch (mode) {
130 case 0:
131 case 1:
132 case 2:
133 case 3:
134 // Do Nothing
135 break;
136 default:
137 error("SPI format error");
138 return;
139 }
140
141 switch (bits) {
142 case 8:
143 DSS = 0x7;
144 splw = 0x20;
145 break;
146 case 16:
147 DSS = 0xf;
148 splw = 0x40;
149 break;
150 case 32:
151 DSS = 0x2;
152 splw = 0x60;
153 break;
154 default:
155 error("SPI module don't support other than 8/16/32bits");
156 return;
157 }
158 tmp |= phase;
159 tmp |= (polarity << 1);
160 tmp |= (DSS << 8);
161 obj->spi.bits = bits;
162
163 spi_disable(obj);
164 wk_spcmd0 = obj->spi.spi->SPCMD0;
165 wk_spcmd0 &= ~mask;
166 wk_spcmd0 |= (mask & tmp);
167 obj->spi.spi->SPCMD0 = wk_spcmd0;
168 obj->spi.spi->SPDCR = splw;
169 if (slave) {
170 obj->spi.spi->SPCR &=~(1 << 3); // MSTR to 0
171 } else {
172 obj->spi.spi->SPCR |= (1 << 3); // MSTR to 1
173 }
174 spi_enable(obj);
175}
176
177void spi_frequency(spi_t *obj, int hz) {
178 uint32_t pclk_base;
179 uint32_t div;
180 uint32_t brdv = 0;
181 uint32_t hz_max;
182 uint32_t hz_min;
183 uint16_t mask = 0x000c;
184 uint16_t wk_spcmd0;
185
186 /* set PCLK */
187 if (RZ_A1_IsClockMode0() == false) {
188 pclk_base = CM1_RENESAS_RZ_A1_P1_CLK;
189 } else {
190 pclk_base = CM0_RENESAS_RZ_A1_P1_CLK;
191 }
192
193 hz_min = pclk_base / 2 / 256 / 8;
194 hz_max = pclk_base / 2;
195 if ((hz < hz_min) || (hz > hz_max)) {
196 error("Couldn't setup requested SPI frequency");
197 return;
198 }
199
200 div = (pclk_base / hz / 2);
201 while (div > 256) {
202 div >>= 1;
203 brdv++;
204 }
205 div -= 1;
206 brdv = (brdv << 2);
207
208 spi_disable(obj);
209 obj->spi.spi->SPBR = div;
210 wk_spcmd0 = obj->spi.spi->SPCMD0;
211 wk_spcmd0 &= ~mask;
212 wk_spcmd0 |= (mask & brdv);
213 obj->spi.spi->SPCMD0 = wk_spcmd0;
214 spi_enable(obj);
215}
216
217static inline void spi_disable(spi_t *obj) {
218 obj->spi.spi->SPCR &= ~(1 << 6); // SPE to 0
219}
220
221static inline void spi_enable(spi_t *obj) {
222 obj->spi.spi->SPCR |= (1 << 6); // SPE to 1
223}
224
225static inline int spi_readable(spi_t *obj) {
226 return obj->spi.spi->SPSR & (1 << 7); // SPRF
227}
228
229static inline int spi_tend(spi_t *obj) {
230 return obj->spi.spi->SPSR & (1 << 6); // TEND
231}
232
233static inline void spi_write(spi_t *obj, int value) {
234 if (obj->spi.bits == 8) {
235 obj->spi.spi->SPDR.UINT8[0] = (uint8_t)value;
236 } else if (obj->spi.bits == 16) {
237 obj->spi.spi->SPDR.UINT16[0] = (uint16_t)value;
238 } else {
239 obj->spi.spi->SPDR.UINT32 = (uint32_t)value;
240 }
241}
242
243static inline int spi_read(spi_t *obj) {
244 int read_data;
245
246 if (obj->spi.bits == 8) {
247 read_data = obj->spi.spi->SPDR.UINT8[0];
248 } else if (obj->spi.bits == 16) {
249 read_data = obj->spi.spi->SPDR.UINT16[0];
250 } else {
251 read_data = obj->spi.spi->SPDR.UINT32;
252 }
253
254 return read_data;
255}
256
257int spi_master_write(spi_t *obj, int value) {
258 spi_write(obj, value);
259 while(!spi_tend(obj));
260 return spi_read(obj);
261}
262
263int spi_slave_receive(spi_t *obj) {
264 return (spi_readable(obj) && !spi_busy(obj)) ? (1) : (0);
265}
266
267int spi_slave_read(spi_t *obj) {
268 return spi_read(obj);
269}
270
271void spi_slave_write(spi_t *obj, int value) {
272 spi_write(obj, value);
273}
274
275int spi_busy(spi_t *obj) {
276 return 0;
277}
278
279#if DEVICE_SPI_ASYNCH
280
281#define IRQ_NUM 2
282
283static void spi_irqs_set(spi_t *obj, uint32_t enable);
284static void spi_async_write(spi_t *obj);
285static void spi_async_read(spi_t *obj);
286
287static void spi0_rx_irq(void);
288static void spi1_rx_irq(void);
289static void spi2_rx_irq(void);
290static void spi3_rx_irq(void);
291static void spi4_rx_irq(void);
292static void spi0_er_irq(void);
293static void spi1_er_irq(void);
294static void spi2_er_irq(void);
295static void spi3_er_irq(void);
296static void spi4_er_irq(void);
297
298static const IRQn_Type irq_set_tbl[RSPI_COUNT][IRQ_NUM] = {
299 {RSPISPRI0_IRQn, RSPISPEI0_IRQn},
300 {RSPISPRI1_IRQn, RSPISPEI1_IRQn},
301 {RSPISPRI2_IRQn, RSPISPEI2_IRQn},
302 {RSPISPRI3_IRQn, RSPISPEI3_IRQn},
303 {RSPISPRI4_IRQn, RSPISPEI4_IRQn}
304};
305
306static const IRQHandler hander_set_tbl[RSPI_COUNT][IRQ_NUM] = {
307 {spi0_rx_irq, spi0_er_irq},
308 {spi1_rx_irq, spi1_er_irq},
309 {spi2_rx_irq, spi2_er_irq},
310 {spi3_rx_irq, spi3_er_irq},
311 {spi4_rx_irq, spi4_er_irq}
312};
313
314struct spi_global_data_s {
315 spi_t *async_obj;
316 uint32_t async_callback, event, wanted_events;
317};
318
319static struct spi_global_data_s spi_data[RSPI_COUNT];
320
321static void spi_rx_irq(IRQn_Type irq_num, uint32_t index)
322{
323 spi_t *obj = spi_data[index].async_obj;
324 if (obj->rx_buff.buffer && obj->rx_buff.pos < obj->rx_buff.length) {
325 spi_async_read(obj);
326 } else {
327 if (obj->rx_buff.buffer && obj->tx_buff.buffer && obj->tx_buff.pos < obj->tx_buff.length) {
328 spi_data[obj->spi.index].event = SPI_EVENT_INTERNAL_TRANSFER_COMPLETE;
329 if (spi_data[obj->spi.index].wanted_events & SPI_EVENT_COMPLETE) {
330 spi_data[obj->spi.index].event |= SPI_EVENT_COMPLETE;
331 }
332 spi_irqs_set(obj, 0);
333 spi_data[obj->spi.index].async_obj = NULL;
334 ((void (*)())spi_data[obj->spi.index].async_callback)();
335 return;
336 }
337 spi_read(obj);
338 }
339 if (obj->tx_buff.buffer) {
340 if (obj->tx_buff.pos == obj->tx_buff.length) {
341 spi_data[obj->spi.index].event = SPI_EVENT_INTERNAL_TRANSFER_COMPLETE;
342 if (spi_data[obj->spi.index].wanted_events & SPI_EVENT_COMPLETE) {
343 spi_data[obj->spi.index].event |= SPI_EVENT_COMPLETE;
344 }
345 spi_irqs_set(obj, 0);
346 spi_data[obj->spi.index].async_obj = NULL;
347 ((void (*)())spi_data[obj->spi.index].async_callback)();
348 } else {
349 spi_async_write(obj);
350 }
351 } else {
352 if (obj->rx_buff.pos == obj->rx_buff.length) {
353 spi_data[obj->spi.index].event = SPI_EVENT_INTERNAL_TRANSFER_COMPLETE;
354 if (spi_data[obj->spi.index].wanted_events & SPI_EVENT_COMPLETE) {
355 spi_data[obj->spi.index].event |= SPI_EVENT_COMPLETE;
356 }
357 spi_irqs_set(obj, 0);
358 spi_data[obj->spi.index].async_obj = NULL;
359 ((void (*)())spi_data[obj->spi.index].async_callback)();
360 } else {
361 spi_async_write(obj);
362 }
363 }
364}
365
366static void spi_err_irq(IRQn_Type irq_num, uint32_t index)
367{
368 spi_t *obj = spi_data[index].async_obj;
369 spi_abort_asynch(obj);
370 spi_data[index].event = SPI_EVENT_ERROR;
371 if (spi_data[index].wanted_events & SPI_EVENT_ERROR) {
372 ((void (*)())spi_data[index].async_callback)();
373 }
374}
375
376static void spi0_rx_irq(void)
377{
378 spi_rx_irq(RSPISPRI0_IRQn, 0);
379}
380
381static void spi1_rx_irq(void)
382{
383 spi_rx_irq(RSPISPRI1_IRQn, 1);
384}
385
386static void spi2_rx_irq(void)
387{
388 spi_rx_irq(RSPISPRI2_IRQn, 2);
389}
390
391static void spi3_rx_irq(void)
392{
393 spi_rx_irq(RSPISPRI3_IRQn, 3);
394}
395
396static void spi4_rx_irq(void)
397{
398 spi_rx_irq(RSPISPRI4_IRQn, 4);
399}
400
401static void spi0_er_irq(void)
402{
403 spi_err_irq(RSPISPEI0_IRQn, 0);
404}
405
406static void spi1_er_irq(void)
407{
408 spi_err_irq(RSPISPEI1_IRQn, 1);
409}
410
411static void spi2_er_irq(void)
412{
413 spi_err_irq(RSPISPEI2_IRQn, 2);
414}
415
416static void spi3_er_irq(void)
417{
418 spi_err_irq(RSPISPEI3_IRQn, 3);
419}
420
421static void spi4_er_irq(void)
422{
423 spi_err_irq(RSPISPEI4_IRQn, 4);
424}
425
426static void spi_irqs_set(spi_t *obj, uint32_t enable)
427{
428 int i;
429 const IRQn_Type *irqTable = irq_set_tbl[obj->spi.index];
430 const IRQHandler *handlerTable = hander_set_tbl[obj->spi.index];
431 for (i = 0; i < IRQ_NUM; ++i) {
432 if (enable) {
433 InterruptHandlerRegister(irqTable[i], handlerTable[i]);
434 GIC_SetPriority(irqTable[i], 5);
435 GIC_EnableIRQ(irqTable[i]);
436 } else {
437 GIC_DisableIRQ(irqTable[i]);
438 }
439 }
440 if (enable) {
441 obj->spi.spi->SPCR |= (1 << 4) | (1 << 7);
442 } else {
443 obj->spi.spi->SPCR &= ~((1 << 4) | (1 << 7));
444 }
445}
446
447static void spi_async_write(spi_t *obj)
448{
449 uint8_t **width8;
450 uint16_t **width16;
451 uint32_t **width32;
452
453 if (obj->tx_buff.buffer) {
454 switch (obj->tx_buff.width) {
455 case 8:
456 width8 = (uint8_t **)&obj->tx_buff.buffer;
457 spi_write(obj, **width8);
458 ++*width8;
459 obj->tx_buff.pos += sizeof(uint8_t);
460 break;
461
462 case 16:
463 width16 = (uint16_t **)&obj->tx_buff.buffer;
464 spi_write(obj, **width16);
465 ++*width16;
466 obj->tx_buff.pos += sizeof(uint16_t);
467 break;
468
469 case 32:
470 width32 = (uint32_t **)&obj->tx_buff.buffer;
471 spi_write(obj, **width32);
472 ++*width32;
473 obj->tx_buff.pos += sizeof(uint32_t);
474 break;
475
476 default:
477 MBED_ASSERT(0);
478 break;
479 }
480 } else {
481 spi_write(obj, SPI_FILL_WORD);
482 }
483}
484
485static void spi_async_read(spi_t *obj)
486{
487 uint8_t **width8;
488 uint16_t **width16;
489 uint32_t **width32;
490
491 switch (obj->rx_buff.width) {
492 case 8:
493 width8 = (uint8_t **)&obj->rx_buff.buffer;
494 **width8 = spi_read(obj);
495 ++*width8;
496 obj->rx_buff.pos += sizeof(uint8_t);
497 break;
498
499 case 16:
500 width16 = (uint16_t **)&obj->rx_buff.buffer;
501 **width16 = spi_read(obj);
502 ++*width16;
503 obj->rx_buff.pos += sizeof(uint16_t);
504 break;
505
506 case 32:
507 width32 = (uint32_t **)&obj->rx_buff.buffer;
508 **width32 = spi_read(obj);
509 ++*width32;
510 obj->rx_buff.pos += sizeof(uint32_t);
511 break;
512
513 default:
514 MBED_ASSERT(0);
515 break;
516 }
517}
518
519/******************************************************************************
520 * ASYNCHRONOUS HAL
521 ******************************************************************************/
522
523void spi_master_transfer(spi_t *obj, const void *tx, size_t tx_length, void *rx, size_t rx_length, uint8_t bit_width, uint32_t handler, uint32_t event, DMAUsage hint)
524{
525 int i;
526 MBED_ASSERT(obj);
527 MBED_ASSERT(tx || rx);
528 MBED_ASSERT(tx && ! rx ? tx_length : 1);
529 MBED_ASSERT(rx && ! tx ? rx_length : 1);
530 MBED_ASSERT(obj->spi.spi->SPCR & (1 << 3)); /* Slave mode */
531 MBED_ASSERT(bit_width == 8 || bit_width == 16 || bit_width == 32);
532
533 if (tx_length) {
534 obj->tx_buff.buffer = (void *)tx;
535 } else {
536 obj->tx_buff.buffer = NULL;
537 }
538 obj->tx_buff.length = tx_length * bit_width / 8;
539 obj->tx_buff.pos = 0;
540 obj->tx_buff.width = bit_width;
541 if (rx_length) {
542 obj->rx_buff.buffer = rx;
543 } else {
544 obj->rx_buff.buffer = NULL;
545 }
546 obj->rx_buff.length = rx_length * bit_width / 8;
547 obj->rx_buff.pos = 0;
548 obj->rx_buff.width = bit_width;
549 for (i = 0; i < obj->rx_buff.length; i++) {
550 ((uint8_t *)obj->rx_buff.buffer)[i] = SPI_FILL_WORD;
551 }
552
553 spi_data[obj->spi.index].async_callback = handler;
554 spi_data[obj->spi.index].async_obj = obj;
555 spi_data[obj->spi.index].event = 0;
556 spi_data[obj->spi.index].wanted_events = event;
557
558 spi_irqs_set(obj, 1);
559
560 spi_async_write(obj);
561}
562
563uint32_t spi_irq_handler_asynch(spi_t *obj)
564{
565 return spi_data[obj->spi.index].event;
566}
567
568uint8_t spi_active(spi_t *obj)
569{
570 return spi_data[obj->spi.index].async_obj != NULL;
571}
572
573void spi_abort_asynch(spi_t *obj)
574{
575 spi_disable(obj);
576 spi_irqs_set(obj, 0);
577 spi_data[obj->spi.index].async_obj = NULL;
578 spi_enable(obj);
579}
580
581#endif
Note: See TracBrowser for help on using the repository browser.