source: azure_iot_hub_f767zi/trunk/asp_baseplatform/pdic/stm32f7xx/spi.c@ 457

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

ファイルを追加

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc;charset=UTF-8
File size: 29.0 KB
Line 
1/*
2 * TOPPERS/ASP Kernel
3 * Toyohashi Open Platform for Embedded Real-Time Systems/
4 * Advanced Standard Profile Kernel
5 *
6 * Copyright (C) 2008-2011 by Embedded and Real-Time Systems Laboratory
7 * Graduate School of Information Science, Nagoya Univ., JAPAN
8 * Copyright (C) 2015-2018 by TOPPERS PROJECT Educational Working Group.
9 *
10 * 上記著作権者は,以下の(1)~(4)の条件を満たす場合に限り,本ソフトウェ
11 * ア(本ソフトウェアを改変したものを含む.以下同じ)を使用・複製・改
12 * 変・再配布(以下,利用と呼ぶ)することを無償で許諾する.
13 * (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
14 * 権表示,この利用条件および下記の無保証規定が,そのままの形でソー
15 * スコード中に含まれていること.
16 * (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
17 * 用できる形で再配布する場合には,再配布に伴うドキュメント(利用
18 * 者マニュアルなど)に,上記の著作権表示,この利用条件および下記
19 * の無保証規定を掲載すること.
20 * (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
21 * 用できない形で再配布する場合には,次のいずれかの条件を満たすこ
22 * と.
23 * (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著
24 * 作権表示,この利用条件および下記の無保証規定を掲載すること.
25 * (b) 再配布の形態を,別に定める方法によって,TOPPERSプロジェクトに
26 * 報告すること.
27 * (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
28 * 害からも,上記著作権者およびTOPPERSプロジェクトを免責すること.
29 * また,本ソフトウェアのユーザまたはエンドユーザからのいかなる理
30 * 由に基づく請求からも,上記著作権者およびTOPPERSプロジェクトを
31 * 免責すること.
32 *
33 * 本ソフトウェアは,無保証で提供されているものである.上記著作権者お
34 * よびTOPPERSプロジェクトは,本ソフトウェアに関して,特定の使用目的
35 * に対する適合性も含めて,いかなる保証も行わない.また,本ソフトウェ
36 * アの利用により直接的または間接的に生じたいかなる損害に関しても,そ
37 * の責任を負わない.
38 *
39 * @(#) $Id$
40 */
41/*
42 *
43 * SPIドライバ関数群
44 *
45 */
46#include "kernel_impl.h"
47#include <t_syslog.h>
48#include <t_stdlib.h>
49#include <string.h>
50#include <sil.h>
51#include <target_syssvc.h>
52#include "device.h"
53#include "spi.h"
54
55#define sil_orw_mem(a, b) sil_wrw_mem((a), sil_rew_mem(a) | (b))
56#define sil_andw_mem(a, b) sil_wrw_mem((a), sil_rew_mem(a) & ~(b))
57#define sil_modw_mem(a, b, c) sil_wrw_mem((a), (sil_rew_mem(a) & (~b)) | (c))
58
59#ifndef SPI_GPIO_PP
60#define SPI_GPIO_PP GPIO_PULLUP
61#endif
62#ifndef SPI_GPIO_SPEED
63#define SPI_GPIO_SPEED GPIO_SPEED_HIGH
64#endif
65
66/*
67 * SPIOポートIDから管理ブロックを取り出すためのマクロ
68 */
69#define INDEX_SPI(spiid) ((uint_t)((spiid) - 1))
70
71#define GPIO_AF5_SPI1 ((uint8_t)0x05) /* SPI1 Alternate Function mapping */
72#define GPIO_AF5_SPI2 ((uint8_t)0x05) /* SPI2 Alternate Function mapping */
73
74#define SPI_TIMEOUT_VALUE (10*1000)
75
76static const SPI_PortControlBlock spi_pcb[NUM_SPIPORT] = {
77 { TADR_SPI1_BASE,
78#if defined(TOPPERS_STM32F723_DISCOVERY)
79 (TADR_RCC_BASE+TOFF_RCC_AHB1ENR), RCC_AHB1ENR_GPIOAEN, RCC_AHB1ENR_GPIOHEN,
80#else
81 (TADR_RCC_BASE+TOFF_RCC_AHB1ENR), RCC_AHB1ENR_GPIOAEN, RCC_AHB1ENR_GPIOAEN,
82#endif
83 (TADR_RCC_BASE+TOFF_RCC_APB2ENR), RCC_APB2ENR_SPI1EN,
84 (TADR_RCC_BASE+TOFF_RCC_AHB1ENR), RCC_AHB1ENR_DMA2EN,
85#if defined(TOPPERS_STM32F723_DISCOVERY)
86 TADR_GPIOA_BASE, TADR_GPIOH_BASE, TADR_GPIOH_BASE,
87 5, 4, 5, GPIO_AF5_SPI1,
88#else
89 TADR_GPIOA_BASE, TADR_GPIOA_BASE, TADR_GPIOA_BASE,
90 5, 6, 7, GPIO_AF5_SPI1,
91#endif
92 DMA_CHANNEL_3, TADR_DMA2_STM3_BASE,
93 DMA_CHANNEL_3, TADR_DMA2_STM2_BASE },
94
95 { TADR_SPI2_BASE,
96#if defined(TOPPERS_STM32F769_DISCOVERY)
97 (TADR_RCC_BASE+TOFF_RCC_AHB1ENR), RCC_AHB1ENR_GPIOAEN, RCC_AHB1ENR_GPIOBEN,
98#else
99 (TADR_RCC_BASE+TOFF_RCC_AHB1ENR), RCC_AHB1ENR_GPIOBEN, RCC_AHB1ENR_GPIOIEN,
100#endif
101 (TADR_RCC_BASE+TOFF_RCC_APB1ENR), RCC_APB1ENR_SPI2EN,
102 (TADR_RCC_BASE+TOFF_RCC_AHB1ENR), RCC_AHB1ENR_DMA1EN,
103#if defined(TOPPERS_STM32F769_DISCOVERY)
104 TADR_GPIOA_BASE, TADR_GPIOB_BASE, TADR_GPIOB_BASE,
105 12, 14, 15, GPIO_AF5_SPI2,
106#elif defined(TOPPERS_STM32F7_DISCOVERY)
107 TADR_GPIOI_BASE, TADR_GPIOB_BASE, TADR_GPIOB_BASE,
108 1, 14, 15, GPIO_AF5_SPI2,
109#else
110 TADR_GPIOB_BASE, TADR_GPIOB_BASE, TADR_GPIOB_BASE,
111 13, 14, 15, GPIO_AF5_SPI2,
112#endif
113 DMA_CHANNEL_0, TADR_DMA1_STM4_BASE,
114 DMA_CHANNEL_0, TADR_DMA1_STM3_BASE },
115};
116
117static SPI_Handle_t SpiHandle[NUM_SPIPORT];
118static DMA_Handle_t hdma_tx[NUM_SPIPORT];
119static DMA_Handle_t hdma_rx[NUM_SPIPORT];
120
121
122/*
123 * SPI状態変化待ち関数
124 * parameter1 hspi: SPIハンドラへのポインタ
125 * parameter2 Flag: チェックを行うSPIフラグ
126 * parameter3 Status: 待ち状態
127 * parameter4 Timeout: タイムアウト時間(マイクロ秒)
128 * return ERコード
129 */
130static ER
131spi_waitflag(SPI_Handle_t *hspi, uint32_t Flag, bool_t Status, uint32_t Timeout)
132{
133 uint32_t tick = 0;
134
135 while(((sil_rew_mem((uint32_t *)(hspi->base+TOFF_SPI_SR)) & Flag) == Flag) == Status){
136 if(Timeout == 0 || tick > Timeout){
137 /*
138 * 送受信とエラーフラグをリセット
139 */
140 sil_andw_mem((uint32_t *)(hspi->base+TOFF_SPI_CR2), (SPI_CR2_TXEIE | SPI_CR2_RXNEIE | SPI_CR2_ERRIE));
141
142 /*
143 * SPIを停止
144 */
145 sil_andw_mem((uint32_t *)(hspi->base+TOFF_SPI_CR1), SPI_CR1_SPE);
146
147 /*
148 * CRC演算を無効に
149 */
150 if(hspi->Init.CRC == SPI_CRC_ENABLE){
151 sil_andw_mem((uint32_t *)(hspi->base+TOFF_SPI_CR1), SPI_CR1_CRCEN);
152 sil_orw_mem((uint32_t *)(hspi->base+TOFF_SPI_CR1), SPI_CR1_CRCEN);
153 }
154
155 hspi->status= SPI_STATUS_READY;
156 return E_TMOUT;
157 }
158 tick++;
159 sil_dly_nse(1000);
160 }
161 return E_OK;
162}
163
164/*
165 * SPI DMA送信コールバック関数
166 */
167static void
168spi_dmatransmit_func(DMA_Handle_t *hdma)
169{
170 SPI_Handle_t* hspi = ( SPI_Handle_t* )hdma->localdata;
171 volatile uint32_t tmp;
172
173 /*
174 * TXEフラグセット待ち
175 */
176 if(spi_waitflag(hspi, SPI_SR_TXE, false, SPI_TIMEOUT_VALUE) != E_OK){
177 hspi->ErrorCode |= SPI_ERROR_TIMEOUT;
178 }
179
180 /*
181 * TX DMA停止
182 */
183 sil_andw_mem((uint32_t *)(hspi->base+TOFF_SPI_CR2), SPI_CR2_TXDMAEN);
184
185 /*
186 * SPI BUSYリセット待ち
187 */
188 if(spi_waitflag(hspi, SPI_SR_BSY, true, SPI_TIMEOUT_VALUE) != E_OK){
189 hspi->ErrorCode |= SPI_ERROR_TIMEOUT;
190 }
191
192 hspi->TxXferCount = 0;
193 hspi->status = SPI_STATUS_READY;
194
195 /*
196 * 2ライン転送でオーバーランが発生しているならリセット
197 */
198 if(hspi->Init.Direction == SPI_DIRECTION_2LINES){
199 tmp = sil_rew_mem((uint32_t *)(hspi->base+TOFF_SPI_DR));
200 sil_andw_mem((uint32_t *)(hspi->base+TOFF_SPI_SR), SPI_SR_OVR);
201 ((void)(tmp));
202 }
203 if(hspi->Init.semid != 0)
204 isig_sem(hspi->Init.semid);
205}
206
207/*
208 * SPI DMA受信コールバック関数
209 */
210static void
211spi_dmareceive_func(DMA_Handle_t *hdma)
212{
213 SPI_Handle_t *hspi = (SPI_Handle_t *)hdma->localdata;
214 volatile uint32_t tmp;
215
216 if((hspi->Init.Mode == SPI_MODE_MASTER) &&
217 (hspi->Init.Direction == SPI_DIRECTION_1LINE || hspi->Init.Direction == SPI_DIRECTION_2LINES_RXONLY)){
218 /*
219 * SPIを停止
220 */
221 sil_andw_mem((uint32_t *)(hspi->base+TOFF_SPI_CR1), SPI_CR1_SPE);
222 }
223
224 /*
225 * RX DMA停止
226 */
227 sil_andw_mem((uint32_t *)(hspi->base+TOFF_SPI_CR2), (SPI_CR2_RXDMAEN));
228
229 hspi->RxXferCount = 0;
230
231 /*
232 * CRC演算
233 */
234 if(hspi->Init.CRC == SPI_CRC_ENABLE){
235 /*
236 * 受信終了待ち
237 */
238 if(spi_waitflag(hspi, SPI_SR_RXNE, false, SPI_TIMEOUT_VALUE) != E_OK){
239 hspi->ErrorCode |= SPI_ERROR_TIMEOUT;
240 }
241
242 /*
243 * CRC読み捨て
244 */
245 tmp = sil_rew_mem((uint32_t *)(hspi->base+TOFF_SPI_DR));
246 ((void)(tmp));
247
248 /*
249 * CRCエラーチェック
250 */
251 if((sil_rew_mem((uint32_t *)(hspi->base+TOFF_SPI_SR)) & SPI_SR_CRCERR) != 0){
252 hspi->ErrorCode |= SPI_ERROR_CRC;
253 sil_andw_mem((uint32_t *)(hspi->base+TOFF_SPI_SR), SPI_SR_CRCERR);
254 }
255 }
256 hspi->status = SPI_STATUS_READY;
257
258 if(hspi->Init.semid != 0)
259 isig_sem(hspi->Init.semid);
260}
261
262/*
263 * SPI DMA送受信コールバック関数
264 */
265static void
266spi_dmatransrecv_func(DMA_Handle_t *hdma)
267{
268 SPI_Handle_t *hspi = (SPI_Handle_t *)hdma->localdata;
269 volatile uint32_t tmp;
270
271 /*
272 * CRC演算
273 */
274 if(hspi->Init.CRC == SPI_CRC_ENABLE){
275 /*
276 * 受信終了待ち
277 */
278 if(spi_waitflag(hspi, SPI_SR_RXNE, false, SPI_TIMEOUT_VALUE) != E_OK){
279 hspi->ErrorCode |= SPI_ERROR_TIMEOUT;
280 }
281 /*
282 * CRC読み捨て
283 */
284 tmp = sil_rew_mem((uint32_t *)(hspi->base+TOFF_SPI_DR));
285 ((void)(tmp));
286
287 /*
288 * CRCエラーチェック
289 */
290 if((sil_rew_mem((uint32_t *)(hspi->base+TOFF_SPI_SR)) & SPI_SR_CRCERR) != 0){
291 hspi->ErrorCode |= SPI_ERROR_CRC;
292 sil_andw_mem((uint32_t *)(hspi->base+TOFF_SPI_SR), SPI_SR_CRCERR);
293 }
294 }
295
296 /*
297 * TXEフラグセット待ち
298 */
299 if(spi_waitflag(hspi, SPI_SR_TXE, false, SPI_TIMEOUT_VALUE) != E_OK){
300 hspi->ErrorCode |= SPI_ERROR_TIMEOUT;
301 }
302 /*
303 * TX DMA停止
304 */
305 sil_andw_mem((uint32_t *)(hspi->base+TOFF_SPI_CR2), (SPI_CR2_TXDMAEN));
306
307 /*
308 * SPI BUSY終了待ち
309 */
310 if(spi_waitflag(hspi, SPI_SR_BSY, true, SPI_TIMEOUT_VALUE) != E_OK){
311 hspi->ErrorCode |= SPI_ERROR_TIMEOUT;
312 }
313
314 /*
315 * RX DMA停止
316 */
317 sil_andw_mem((uint32_t *)(hspi->base+TOFF_SPI_CR2), (SPI_CR2_RXDMAEN));
318
319 hspi->TxXferCount = 0;
320 hspi->RxXferCount = 0;
321 hspi->status = SPI_STATUS_READY;
322
323 if(hspi->Init.semid != 0)
324 isig_sem(hspi->Init.semid);
325}
326
327/*
328 * SPI内部転送終了待ち
329 */
330ER
331spi_inwait(SPI_Handle_t *hspi, uint32_t timeout)
332{
333 ER ercd = E_OK;
334 int tick = timeout;
335
336 while((hspi->status & SPI_STATUS_BUSY) != 0 && tick > 0){
337 if(hspi->Init.semid != 0)
338 twai_sem(hspi->Init.semid, 1);
339 else
340 dly_tsk(1);
341 tick--;
342 }
343 dma_end(hspi->hdmarx);
344 dma_end(hspi->hdmatx);
345 if(hspi->ErrorCode != 0)
346 ercd = E_OBJ;
347 else if(tick == 0)
348 ercd = E_TMOUT;
349 hspi->TxXferCount = 0;
350 hspi->RxXferCount = 0;
351 return ercd;
352}
353
354/*
355 * SPI DMAエラーコールバック関数
356 */
357static
358void spi_dmaerror_func(DMA_Handle_t *hdma)
359{
360 SPI_Handle_t *hspi = (SPI_Handle_t *)hdma->localdata;
361
362 hspi->TxXferCount = 0;
363 hspi->RxXferCount = 0;
364 hspi->status= SPI_STATUS_READY;
365 hspi->ErrorCode |= SPI_ERROR_DMA;
366 syslog_2(LOG_ERROR, "SPI DMA Error handle[%08x] ErrorCode[%08x] !", hdma, hdma->ErrorCode);
367 sil_dly_nse(1000*500); /* エラー時ハングアップ回避の0.5msec待ち */
368}
369
370/*
371 * SPI初期設定
372 * parameter1 port: SPIポート番号
373 * parameter2 spii: SPI初期設定構造体へのポインタ
374 * return SPIハンドラへのポインタ、NULLでエラー
375 */
376SPI_Handle_t *
377spi_init(ID port, SPI_Init_t *spii)
378{
379 GPIO_Init_t GPIO_Init_Data;
380 SPI_Handle_t *hspi;
381 const SPI_PortControlBlock *spcb;
382 DMA_Handle_t *hdma;
383 uint32_t no;
384 uint32_t frxth;
385 volatile uint32_t tmpreg;
386
387 if(port < SPI1_PORTID || port > NUM_SPIPORT)
388 return NULL;
389 if(spii == NULL)
390 return NULL;
391
392 no = INDEX_SPI(port);
393 hspi = &SpiHandle[no];
394 if(hspi->status != SPI_STATUS_RESET)
395 return NULL;
396 spcb = &spi_pcb[no];
397 memcpy(&hspi->Init, spii, sizeof(SPI_Init_t));
398 hspi->base = spcb->base;
399
400 /*
401 * SPI クロック設定
402 */
403 sil_orw_mem((uint32_t *)spcb->gioclockbase, spcb->gioclockbit);
404 tmpreg = sil_rew_mem((uint32_t *)spcb->gioclockbase);
405 sil_orw_mem((uint32_t *)spcb->gioclockbase, spcb->gioclockbit2);
406 tmpreg = sil_rew_mem((uint32_t *)spcb->gioclockbase);
407 sil_orw_mem((uint32_t *)spcb->spiclockbase, spcb->spiclockbit);
408 tmpreg = sil_rew_mem((uint32_t *)spcb->spiclockbase);
409 sil_orw_mem((uint32_t *)spcb->dmaclockbase, spcb->dmaclockbit);
410 tmpreg = sil_rew_mem((uint32_t *)spcb->dmaclockbase);
411 ((void)(tmpreg));
412
413 /*
414 * SPI GPIOピン設定
415 */
416 GPIO_Init_Data.mode = GPIO_MODE_AF;
417 GPIO_Init_Data.pull = SPI_GPIO_PP;
418 GPIO_Init_Data.otype = GPIO_OTYPE_PP;
419 GPIO_Init_Data.speed = SPI_GPIO_SPEED;
420 GPIO_Init_Data.alternate = spcb->apvalue;
421 gpio_setup(spcb->giobase1, &GPIO_Init_Data, spcb->sckpin);
422 gpio_setup(spcb->giobase2, &GPIO_Init_Data, spcb->misopin);
423 gpio_setup(spcb->giobase3, &GPIO_Init_Data, spcb->mosipin);
424
425 /*
426 * SPI用受信DMP設定
427 */
428 hdma = &hdma_tx[no];
429 hdma->base = spcb->dmatxbase;
430 hdma->Init.Channel = spcb->dmatxchannel;
431 hdma->Init.Direction = DMA_MEMORY_TO_PERIPH;
432 hdma->Init.PeriphInc = DMA_PINC_DISABLE;
433 hdma->Init.MemInc = DMA_MINC_ENABLE;
434 hdma->Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
435 hdma->Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
436 hdma->Init.Mode = DMA_NORMAL;
437 hdma->Init.Priority = DMA_PRIORITY_LOW;
438 hdma->Init.FIFOMode = DMA_FIFOMODE_DISABLE;
439 hdma->Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
440 hdma->Init.MemBurst = DMA_MBURST_INC4;
441 hdma->Init.PeriphBurst = DMA_PBURST_INC4;
442
443 dma_init(hdma);
444 hspi->hdmatx = hdma;
445 hdma->localdata = hspi;
446
447 /*
448 * SPI用受信DMP設定
449 */
450 hdma = &hdma_rx[no];
451 hdma->base = spcb->dmarxbase;
452 hdma->Init.Channel = spcb->dmarxchannel;
453 hdma->Init.Direction = DMA_PERIPH_TO_MEMORY;
454 hdma->Init.PeriphInc = DMA_PINC_DISABLE;
455 hdma->Init.MemInc = DMA_MINC_ENABLE;
456 hdma->Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
457 hdma->Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
458 hdma->Init.Mode = DMA_NORMAL;
459 hdma->Init.Priority = DMA_PRIORITY_HIGH;
460 hdma->Init.FIFOMode = DMA_FIFOMODE_DISABLE;
461 hdma->Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
462 hdma->Init.MemBurst = DMA_MBURST_INC4;
463 hdma->Init.PeriphBurst = DMA_PBURST_INC4;
464
465 dma_init(hdma);
466 hspi->hdmarx = hdma;
467 hdma->localdata = hspi;
468
469 /*
470 * SPIディゼーブル
471 */
472 sil_andw_mem((uint32_t *)(hspi->base+TOFF_SPI_CR1), SPI_CR1_SPE);
473
474 /*
475 * FIFOスレッシュホールド設定
476 */
477 if(hspi->Init.DataSize > SPI_DATASIZE_8BIT)
478 frxth = 0x00000000;
479 else
480 frxth = SPI_CR2_FRXTH;
481
482 /*
483 * CRC長の再設定
484 */
485 if(hspi->Init.DataSize != SPI_DATASIZE_16BIT && hspi->Init.DataSize != SPI_DATASIZE_8BIT)
486 hspi->Init.CRC = SPI_CRC_DISABLE;
487 if(hspi->Init.CRCLength == SPI_CRC_LENGTH_DATASIZE){
488 if(hspi->Init.DataSize > SPI_DATASIZE_8BIT)
489 hspi->Init.CRCLength = SPI_CRC_LENGTH_16BIT;
490 else
491 hspi->Init.CRCLength = SPI_CRC_LENGTH_8BIT;
492 }
493
494 /*
495 * SPI CR1/CR2レジスタ設定
496 */
497 sil_wrw_mem((uint32_t *)(hspi->base+TOFF_SPI_CR1), (hspi->Init.Mode | hspi->Init.Direction |
498 hspi->Init.CLKPolarity | hspi->Init.CLKPhase | (hspi->Init.NSS & SPI_CR1_SSM) |
499 hspi->Init.Prescaler | hspi->Init.SignBit | hspi->Init.CRC));
500
501 /*
502 * SPI NSS設定
503 */
504 sil_wrw_mem((uint32_t *)(hspi->base+TOFF_SPI_CR2), (((hspi->Init.NSS >> 16) & SPI_CR2_SSOE) | hspi->Init.TIMode |
505 hspi->Init.DataSize | frxth));
506
507 /*
508 * SPI CRC多項式設定
509 */
510 sil_wrw_mem((uint32_t *)(hspi->base+TOFF_SPI_CRCPR), hspi->Init.CRCPolynomial);
511
512 /*
513 * SPI I2CSモードをリセット
514 */
515 sil_andw_mem((uint32_t *)(hspi->base+TOFF_SPI_I2SCFGR), SPI_I2SCFGR_I2SMOD);
516
517 hspi->ErrorCode = SPI_ERROR_NONE;
518 hspi->status = SPI_STATUS_READY;
519 return hspi;
520}
521
522/*
523 * SPI終了設定
524 * parameter1 hspi: SPIハンドラへのポインタ
525 * return ERコード
526 */
527ER
528spi_deinit(SPI_Handle_t *hspi)
529{
530 if(hspi == NULL)
531 return E_PAR;
532
533 dma_deinit(hspi->hdmatx);
534 dma_deinit(hspi->hdmarx);
535
536 sil_andw_mem((uint32_t *)(hspi->base+TOFF_SPI_CR1), SPI_CR1_SPE);
537
538 hspi->ErrorCode = SPI_ERROR_NONE;
539 hspi->status = SPI_STATUS_RESET;
540 return E_OK;
541}
542
543/*
544 * SPIモジュールのリセット
545 * parameter1 hspi: SPIハンドラへのポインタ
546 * return ERコード
547 */
548ER
549spi_reset(SPI_Handle_t *hspi)
550{
551 uint32_t frxth;
552
553 if(hspi == NULL)
554 return E_PAR;
555 /*
556 * SPIディゼーブル
557 */
558 sil_andw_mem((uint32_t *)(hspi->base+TOFF_SPI_CR1), SPI_CR1_SPE);
559
560 /*
561 * FIFOスレッシュホールド設定
562 */
563 if(hspi->Init.DataSize > SPI_DATASIZE_8BIT)
564 frxth = 0x00000000;
565 else
566 frxth = SPI_CR2_FRXTH;
567
568 /*
569 * CRC長の再設定
570 */
571 if(hspi->Init.DataSize != SPI_DATASIZE_16BIT && hspi->Init.DataSize != SPI_DATASIZE_8BIT)
572 hspi->Init.CRC = SPI_CRC_DISABLE;
573 if(hspi->Init.CRCLength == SPI_CRC_LENGTH_DATASIZE){
574 if(hspi->Init.DataSize > SPI_DATASIZE_8BIT)
575 hspi->Init.CRCLength = SPI_CRC_LENGTH_16BIT;
576 else
577 hspi->Init.CRCLength = SPI_CRC_LENGTH_8BIT;
578 }
579
580 /*
581 * SPI CR1/CR2レジスタ設定
582 */
583 sil_wrw_mem((uint32_t *)(hspi->base+TOFF_SPI_CR1), (hspi->Init.Mode | hspi->Init.Direction |
584 hspi->Init.CLKPolarity | hspi->Init.CLKPhase | (hspi->Init.NSS & SPI_CR1_SSM) |
585 hspi->Init.Prescaler | hspi->Init.SignBit | hspi->Init.CRC));
586
587 /*
588 * SPI NSS設定
589 */
590 sil_wrw_mem((uint32_t *)(hspi->base+TOFF_SPI_CR2), (((hspi->Init.NSS >> 16) & SPI_CR2_SSOE) | hspi->Init.TIMode |
591 hspi->Init.DataSize | frxth));
592
593 /*
594 * SPI CRC多項式設定
595 */
596 sil_wrw_mem((uint32_t *)(hspi->base+TOFF_SPI_CRCPR), hspi->Init.CRCPolynomial);
597
598 /*
599 * SPI I2CSモードをリセット
600 */
601 sil_andw_mem((uint32_t *)(hspi->base+TOFF_SPI_I2SCFGR), SPI_I2SCFGR_I2SMOD);
602
603 hspi->ErrorCode = SPI_ERROR_NONE;
604 hspi->status = SPI_STATUS_READY;
605 return E_OK;
606}
607
608/*
609 * SPI送信実行関数
610 * parameter1 hspi: SPIハンドラへのポインタ
611 * parameter2 pdata: 送信バッファへのポインタ(4バイトアライン)
612 * parameter3 length: 送信サイズ(CRCでは+1)
613 * return ERコード
614 */
615ER
616spi_transmit(SPI_Handle_t *hspi, uint8_t *pdata, uint16_t length)
617{
618 ER ercd = E_OK;
619
620 if(hspi == NULL || pdata == NULL || length == 0)
621 return E_PAR;
622 if((((uint32_t)pdata) & 3) != 0)
623 return E_PAR;
624
625 if(hspi->Init.semlock != 0)
626 wai_sem(hspi->Init.semlock);
627 if(hspi->status != SPI_STATUS_READY){
628 if(hspi->Init.semlock != 0)
629 sig_sem(hspi->Init.semlock);
630 return E_OBJ;
631 }
632
633 /* Configure communication */
634 hspi->xmode = SPI_XMODE_TX;
635 hspi->status = SPI_STATUS_BUSY;
636 hspi->ErrorCode = SPI_ERROR_NONE;
637
638 hspi->pTxBuffPtr = pdata;
639 hspi->TxXferSize = length;
640 hspi->TxXferCount = length;
641 hspi->RxXferSize = 0;
642 hspi->RxXferCount = 0;
643
644 /*
645 * 1ライン通信設定
646 */
647 if(hspi->Init.Direction == SPI_DIRECTION_1LINE){
648 sil_orw_mem((uint32_t *)(hspi->base+TOFF_SPI_CR1), SPI_CR1_BIDIOE);
649 }
650
651 /*
652 * CRCモードなら設定を有効に
653 */
654 if(hspi->Init.CRC == SPI_CRC_ENABLE){
655 sil_andw_mem((uint32_t *)(hspi->base+TOFF_SPI_CR1), SPI_CR1_CRCEN);
656 sil_orw_mem((uint32_t *)(hspi->base+TOFF_SPI_CR1), SPI_CR1_CRCEN);
657 }
658
659 /*
660 * 送信DMAコントローラ設定
661 */
662 hspi->hdmatx->xferhalfcallback = NULL;
663 hspi->hdmatx->xfercallback = spi_dmatransmit_func;
664 hspi->hdmatx->errorcallback = spi_dmaerror_func;
665
666 /*
667 * LAST DMA設定
668 */
669 sil_andw_mem((uint32_t *)(hspi->base+TOFF_SPI_CR2), SPI_CR2_LDMATX);
670 if(hspi->Init.DataSize <= SPI_DATASIZE_8BIT && hspi->hdmatx->Init.MemDataAlignment == DMA_MDATAALIGN_HALFWORD){
671 /* Check the even/odd of the data size + crc if enabled */
672 if((hspi->TxXferCount & 0x1) == 0){
673 sil_andw_mem((uint32_t *)(hspi->base+TOFF_SPI_CR2), SPI_CR2_LDMATX);
674 hspi->TxXferCount = (hspi->TxXferCount >> 1);
675 }
676 else{
677 sil_orw_mem((uint32_t *)(hspi->base+TOFF_SPI_CR2), SPI_CR2_LDMATX);
678 hspi->TxXferCount = (hspi->TxXferCount >> 1) + 1;
679 }
680 }
681
682 /*
683 * 送信DMAコントローラ設定
684 */
685 dma_start(hspi->hdmatx, (uint32_t)hspi->pTxBuffPtr, (uint32_t)(hspi->base+TOFF_SPI_DR), hspi->TxXferCount);
686
687 /* SPI有効化 */
688 if((sil_rew_mem((uint32_t *)(hspi->base+TOFF_SPI_CR1)) & SPI_CR1_SPE) == 0)
689 sil_orw_mem((uint32_t *)(hspi->base+TOFF_SPI_CR1), SPI_CR1_SPE);
690
691 /*
692 * SPI送信DMA設定
693 */
694 sil_orw_mem((uint32_t *)(hspi->base+TOFF_SPI_CR2), SPI_CR2_TXDMAEN);
695
696#if SPI_WAIT_TIME != 0
697 ercd = spi_inwait(hspi, SPI_WAIT_TIME * length);
698
699 if(hspi->Init.semlock != 0)
700 sig_sem(hspi->Init.semlock);
701#endif
702 return ercd;
703}
704
705/*
706 * SPI受信実行関数
707 * parameter1 hspi: SPIハンドラへのポインタ
708 * parameter2 pdata: 受信バッファへのポインタ(4バイトアライン)
709 * parameter3 length: 送信サイズ(CRCでは+1)
710 * return ERコード
711 */
712ER
713spi_receive(SPI_Handle_t *hspi, uint8_t *pdata, uint16_t length)
714{
715 ER ercd = E_OK;
716
717 if(hspi == NULL || pdata == NULL || length == 0)
718 return E_PAR;
719 if((((uint32_t)pdata) & 3) != 0)
720 return E_PAR;
721
722 if(hspi->Init.semlock != 0)
723 wai_sem(hspi->Init.semlock);
724 if(hspi->status != SPI_STATUS_READY){
725 if(hspi->Init.semlock != 0)
726 sig_sem(hspi->Init.semlock);
727 return E_OBJ;
728 }
729
730 /*
731 * 転送情報を設定
732 */
733 hspi->xmode = SPI_XMODE_RX;
734 hspi->status = SPI_STATUS_BUSY;
735 hspi->ErrorCode = SPI_ERROR_NONE;
736 hspi->pRxBuffPtr = pdata;
737 hspi->RxXferSize = length;
738 hspi->RxXferCount = length;
739 hspi->TxXferSize = 0;
740 hspi->TxXferCount = 0;
741
742 /*
743 * 1ライン通信設定
744 */
745 if(hspi->Init.Direction == SPI_DIRECTION_1LINE){
746 sil_andw_mem((uint32_t *)(hspi->base+TOFF_SPI_CR1), SPI_CR1_BIDIOE);
747 }
748 else if(hspi->Init.Direction == SPI_DIRECTION_2LINES){
749 hspi->status = SPI_STATUS_READY;
750 if(hspi->Init.semlock != 0)
751 sig_sem(hspi->Init.semlock);
752 if(hspi->Init.Mode == SPI_MODE_MASTER){
753 /*
754 * 送受信を行う
755 */
756 memset(pdata, 0xff, length);
757 return spi_transrecv(hspi, pdata, pdata, length);
758 }
759 else
760 return E_PAR;
761 }
762
763 /*
764 * CRCモードなら設定を有効に
765 */
766 if(hspi->Init.CRC == SPI_CRC_ENABLE){
767 sil_andw_mem((uint32_t *)(hspi->base+TOFF_SPI_CR1), SPI_CR1_CRCEN);
768 sil_orw_mem((uint32_t *)(hspi->base+TOFF_SPI_CR1), SPI_CR1_CRCEN);
769 }
770
771 /*
772 * スレッシュホールド設定
773 */
774 sil_andw_mem((uint32_t *)(hspi->base+TOFF_SPI_CR2), SPI_CR2_LDMARX);
775 if( hspi->Init.DataSize > SPI_DATASIZE_8BIT){
776 sil_andw_mem((uint32_t *)(hspi->base+TOFF_SPI_CR2), SPI_CR2_FRXTH);
777 }
778 else{
779 sil_orw_mem((uint32_t *)(hspi->base+TOFF_SPI_CR2), SPI_CR2_FRXTH);
780 }
781
782 /*
783 * DMA受信コールバック関数設定
784 */
785 if((hspi->Init.Mode == SPI_MODE_MASTER)
786 && (hspi->Init.Direction == SPI_DIRECTION_1LINE || hspi->Init.Direction == SPI_DIRECTION_2LINES_RXONLY)){
787 hspi->hdmarx->xfercallback = spi_dmareceive_func;
788 }
789 else{
790 hspi->hdmarx->xfercallback = spi_dmatransrecv_func;
791 }
792 hspi->hdmarx->xferhalfcallback = NULL;
793 hspi->hdmarx->errorcallback = spi_dmaerror_func;
794
795 /*
796 * 受信DMAコントローラ設定
797 */
798 dma_start(hspi->hdmarx, (uint32_t)(hspi->base+TOFF_SPI_DR), (uint32_t)hspi->pRxBuffPtr, hspi->RxXferCount);
799
800 /* SPI有効化 */
801 if((sil_rew_mem((uint32_t *)(hspi->base+TOFF_SPI_CR1)) & SPI_CR1_SPE) == 0)
802 sil_orw_mem((uint32_t *)(hspi->base+TOFF_SPI_CR1), SPI_CR1_SPE);
803
804 /*
805 * SPI受信DMA設定
806 */
807 sil_orw_mem((uint32_t *)(hspi->base+TOFF_SPI_CR2), (SPI_CR2_RXDMAEN));
808
809#if SPI_WAIT_TIME != 0
810 ercd = spi_inwait(hspi, SPI_WAIT_TIME * length);
811
812 if(hspi->Init.semlock != 0)
813 sig_sem(hspi->Init.semlock);
814#endif
815 return ercd;
816}
817
818/*
819 * SPI送受信実行関数
820 * parameter1 hspi: SPIハンドラへのポインタ
821 * parameter2 ptxdata: 送信バッファへのポインタ(4バイトアライン)
822 * parameter3 prxdata: 受信バッファへのポインタ(4バイトアライン)
823 * parameter4 length: 送信サイズ(CRCでは+1)
824 * return ERコード
825 */
826ER
827spi_transrecv(SPI_Handle_t *hspi, uint8_t *ptxdata, uint8_t *prxdata, uint16_t length)
828{
829 ER ercd = E_OK;
830
831 if(hspi == NULL || prxdata == NULL || length == 0)
832 return E_PAR;
833 if((((uint32_t)ptxdata) & 3) != 0 || (((uint32_t)prxdata) & 3) != 0)
834 return E_PAR;
835 if(hspi->Init.Direction != SPI_DIRECTION_2LINES && hspi->Init.Mode != SPI_MODE_MASTER)
836 return E_PAR;
837
838 if(hspi->Init.semlock != 0)
839 wai_sem(hspi->Init.semlock);
840 if(hspi->status != SPI_STATUS_READY){
841 if(hspi->Init.semlock != 0)
842 sig_sem(hspi->Init.semlock);
843 return E_OBJ;
844 }
845
846 hspi->xmode = SPI_XMODE_TXRX;
847 hspi->status = SPI_STATUS_BUSY;
848
849 /*
850 * 転送情報を設定
851 */
852 hspi->ErrorCode = SPI_ERROR_NONE;
853 hspi->pTxBuffPtr = (uint8_t*)ptxdata;
854 hspi->TxXferSize = length;
855 hspi->TxXferCount = length;
856 hspi->pRxBuffPtr = (uint8_t*)prxdata;
857 hspi->RxXferSize = length;
858 hspi->RxXferCount = length;
859
860 /*
861 * CRCモードなら設定を有効に
862 */
863 if(hspi->Init.CRC == SPI_CRC_ENABLE){
864 sil_andw_mem((uint32_t *)(hspi->base+TOFF_SPI_CR1), SPI_CR1_CRCEN);
865 sil_orw_mem((uint32_t *)(hspi->base+TOFF_SPI_CR1), SPI_CR1_CRCEN);
866 }
867
868 /*
869 * LAST DMAとスレッシュホールド設定
870 */
871 sil_andw_mem((uint32_t *)(hspi->base+TOFF_SPI_CR2), SPI_CR2_LDMATX);
872 sil_andw_mem((uint32_t *)(hspi->base+TOFF_SPI_CR2), SPI_CR2_LDMARX);
873 if(hspi->Init.DataSize > SPI_DATASIZE_8BIT){
874 sil_andw_mem((uint32_t *)(hspi->base+TOFF_SPI_CR2), SPI_CR2_FRXTH);
875 }
876 else{
877 sil_orw_mem((uint32_t *)(hspi->base+TOFF_SPI_CR2), SPI_CR2_FRXTH);
878 if(hspi->hdmatx->Init.MemDataAlignment == DMA_MDATAALIGN_HALFWORD){
879 if((hspi->TxXferSize & 0x1) == 0x0 ){
880 sil_andw_mem((uint32_t *)(hspi->base+TOFF_SPI_CR2), SPI_CR2_LDMATX);
881 hspi->TxXferCount = hspi->TxXferCount >> 1;
882 }
883 else{
884 sil_orw_mem((uint32_t *)(hspi->base+TOFF_SPI_CR2), SPI_CR2_LDMATX);
885 hspi->TxXferCount = (hspi->TxXferCount >> 1) + 1;
886 }
887 }
888 if(hspi->hdmarx->Init.MemDataAlignment == DMA_MDATAALIGN_HALFWORD){
889 sil_andw_mem((uint32_t *)(hspi->base+TOFF_SPI_CR2), SPI_CR2_FRXTH);
890 if((hspi->RxXferCount & 0x1) == 0){
891 sil_andw_mem((uint32_t *)(hspi->base+TOFF_SPI_CR2), SPI_CR2_LDMARX);
892 hspi->RxXferCount = hspi->RxXferCount >> 1;
893 }
894 else{
895 sil_orw_mem((uint32_t *)(hspi->base+TOFF_SPI_CR2), SPI_CR2_LDMARX);
896 hspi->RxXferCount = (hspi->RxXferCount >> 1) + 1;
897 }
898 }
899 }
900
901 /*
902 * DMA受信コールバック関数設定
903 */
904 if((hspi->Init.Mode == SPI_MODE_MASTER)
905 && (hspi->Init.Direction == SPI_DIRECTION_1LINE || hspi->Init.Direction == SPI_DIRECTION_2LINES_RXONLY)){
906 hspi->hdmarx->xfercallback = spi_dmareceive_func;
907 }
908 else{
909 hspi->hdmarx->xfercallback = spi_dmatransrecv_func;
910 }
911 hspi->hdmarx->xferhalfcallback = NULL;
912 hspi->hdmarx->errorcallback = spi_dmaerror_func;
913
914 /*
915 * 受信DMAコントローラ設定
916 */
917 dma_start(hspi->hdmarx, (uint32_t)(hspi->base+TOFF_SPI_DR), (uint32_t)hspi->pRxBuffPtr, hspi->RxXferCount);
918
919 /*
920 * SPI受信DMA設定
921 */
922 sil_orw_mem((uint32_t *)(hspi->base+TOFF_SPI_CR2), SPI_CR2_RXDMAEN);
923
924 /*
925 * DMA送信コールバックの設定
926 */
927 hspi->hdmatx->xfercallback = NULL;
928 hspi->hdmatx->errorcallback = spi_dmaerror_func;
929
930 /*
931 * 送信DMAコントローラ設定
932 */
933 dma_start(hspi->hdmatx, (uint32_t)hspi->pTxBuffPtr, (uint32_t)(hspi->base+TOFF_SPI_DR), hspi->TxXferCount);
934
935 /*
936 * SPIエラー割込み設定
937 */
938 sil_orw_mem((uint32_t *)(hspi->base+TOFF_SPI_CR2), SPI_CR2_ERRIE);
939
940 /* SPI有効化 */
941 if((sil_rew_mem((uint32_t *)(hspi->base+TOFF_SPI_CR1)) & SPI_CR1_SPE) == 0)
942 sil_orw_mem((uint32_t *)(hspi->base+TOFF_SPI_CR1), SPI_CR1_SPE);
943
944 /*
945 * SPI送信DMA設定
946 */
947 sil_orw_mem((uint32_t *)(hspi->base+TOFF_SPI_CR2), SPI_CR2_TXDMAEN);
948
949#if SPI_WAIT_TIME != 0
950 ercd = spi_inwait(hspi, SPI_WAIT_TIME * length);
951
952 if(hspi->Init.semlock != 0)
953 sig_sem(hspi->Init.semlock);
954#endif
955 return ercd;
956}
957
958/*
959 * SPI転送終了待ち
960 */
961ER
962spi_wait(SPI_Handle_t *hspi, uint32_t timeout)
963{
964 ER ercd = E_OK;
965
966#if SPI_WAIT_TIME == 0
967 if(hspi == NULL)
968 return E_PAR;
969 ercd = spi_inwait(hspi, timeout);
970 if(hspi->Init.semlock != 0)
971 sig_sem(hspi->Init.semlock);
972#endif
973 return ercd;
974}
975
976/*
977 * SPI割込みサービスルーチン
978 */
979void
980spi_handler(SPI_Handle_t *hspi)
981{
982 volatile uint32_t tmp3 = 0;
983
984 /*
985 * 割込みエラー判定
986 */
987 if((sil_rew_mem((uint32_t *)(hspi->base+TOFF_SPI_CR2)) & SPI_CR2_ERRIE) != 0){
988 /*
989 * SPI CRCエラー判定
990 */
991 if((sil_rew_mem((uint32_t *)(hspi->base+TOFF_SPI_SR)) & SPI_SR_CRCERR) != 0){
992 hspi->ErrorCode |= SPI_ERROR_CRC;
993 sil_andw_mem((uint32_t *)(hspi->base+TOFF_SPI_SR), SPI_SR_CRCERR);
994 }
995 /*
996 * SPI モードフォルト判定
997 */
998 if((sil_rew_mem((uint32_t *)(hspi->base+TOFF_SPI_SR)) & SPI_SR_MODF) != 0){
999 hspi->ErrorCode |= SPI_ERROR_MODF;
1000 sil_andw_mem((uint32_t *)(hspi->base+TOFF_SPI_SR), SPI_SR_MODF);
1001 sil_andw_mem((uint32_t *)(hspi->base+TOFF_SPI_CR1), SPI_CR1_SPE);
1002 }
1003 /*
1004 * SPI オーバーラン判定
1005 */
1006 if((sil_rew_mem((uint32_t *)(hspi->base+TOFF_SPI_SR)) & SPI_SR_OVR) != 0){
1007 if(hspi->xmode != SPI_XMODE_TX){
1008 hspi->ErrorCode |= SPI_ERROR_OVR;
1009 tmp3 = sil_rew_mem((uint32_t *)(hspi->base+TOFF_SPI_DR));
1010 ((void)(tmp3));
1011 sil_andw_mem((uint32_t *)(hspi->base+TOFF_SPI_SR), SPI_SR_OVR);
1012 }
1013 }
1014 /*
1015 * SPI フレームエラー判定
1016 */
1017 if((sil_rew_mem((uint32_t *)(hspi->base+TOFF_SPI_SR)) & SPI_SR_FRE) != 0){
1018 hspi->ErrorCode |= SPI_ERROR_FRE;
1019 sil_andw_mem((uint32_t *)(hspi->base+TOFF_SPI_SR), SPI_SR_FRE);
1020 }
1021 /*
1022 * エラー発生時はレディに戻す
1023 */
1024 if(hspi->ErrorCode != SPI_ERROR_NONE){
1025 sil_andw_mem((uint32_t *)(hspi->base+TOFF_SPI_CR1), SPI_CR1_SPE);
1026 hspi->status = SPI_STATUS_READY;
1027 syslog_2(LOG_ERROR, "spi hanndler error[%08x] ErrorCode[%08x] !", hspi, hspi->ErrorCode);
1028 }
1029 }
1030}
1031
1032
1033/*
1034 * SPI割込みサービスルーチン
1035 */
1036void spi_isr(intptr_t exinf)
1037{
1038 spi_handler(&SpiHandle[INDEX_SPI((uint32_t)exinf)]);
1039}
1040
Note: See TracBrowser for help on using the repository browser.