source: azure_iot_hub_riscv/trunk/asp_baseplatform/pdic/k210/spi.c@ 458

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

SPIとSerial、KPUの動作を改善

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc;charset=UTF-8
File size: 25.8 KB
RevLine 
[453]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-2019 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
55Inline uint64_t
56sil_rel_mem(const uint64_t *mem)
57{
[458]58 uint64_t data;
[453]59
[458]60 data = *((const volatile uint64_t *)mem);
61 return (data);
[453]62}
63
[458]64#define sil_orw_mem(a, b) sil_wrw_mem((a), sil_rew_mem(a) | (b))
65#define sil_andw_mem(a, b) sil_wrw_mem((a), sil_rew_mem(a) & ~(b))
66#define sil_modw_mem(a, b, c) sil_wrw_mem((a), (sil_rew_mem(a) & (~b)) | (c))
[453]67
68/*
69 * SPIOポートIDから管理ブロックを取り出すためのマクロ
70 */
[458]71#define INDEX_SPI(spiid) ((uint_t)((spiid)-1))
[453]72
[458]73#define get_framewidth(l) (((l) + 7) / 8)
[453]74
[458]75#define SPI_SSIENR_DISABLE 0x00000000
76#define SPI_SSIENR_ENABLE 0x00000001
[453]77
[458]78#define SPI_DMACR_RXENABLE 0x00000001
79#define SPI_DMACR_TXENABLE 0x00000002
[453]80
81/*
82 * SPIハードウェア設定構造体
83 */
84
[458]85typedef struct _SPI_PortControlBlock {
86 unsigned long base;
87 int16_t func_data;
88 int16_t func_ss;
89 int16_t func_arb;
90 int16_t func_sclk;
[453]91} SPI_PortControlBlock;
92
93static const SPI_PortControlBlock spi_pcb[NUM_SPIPORT] = {
[458]94 {TADR_SPI0_BASE, FUNC_SPI0_D0, FUNC_SPI0_SS0, FUNC_SPI0_ARB, FUNC_SPI0_SCLK},
95 {TADR_SPI1_BASE, FUNC_SPI1_D0, FUNC_SPI1_SS0, FUNC_SPI1_ARB, FUNC_SPI1_SCLK},
[453]96 {TADR_SPIS_BASE, FUNC_SPI_SLAVE_D0, FUNC_SPI_SLAVE_SS, -1, FUNC_SPI_SLAVE_SCLK},
[458]97 {TADR_SPI2_BASE, -1, -1, -1, -1}
[453]98};
99
100SPI_Handle_t SpiHandle[NUM_SPIPORT];
101DMA_Handle_t spi_dma_handle[NUM_SPIPORT][2];
102
103
104/*
105 * 転送モード設定
106 */
107static ER
108spi_set_tmod(SPI_Handle_t *hspi, uint32_t tmod)
109{
110 SPI_Init_t *init;
[458]111 uint32_t inst_l = 4;
112 uint32_t addr_l;
[453]113
114 init = &hspi->Init;
[458]115 switch (init->InstLength) {
[453]116 case 0:
117 inst_l = 0;
118 break;
119 case 4:
120 inst_l = 1;
121 break;
122 case 8:
123 inst_l = 2;
124 break;
125 case 16:
126 inst_l = 3;
127 break;
128 default:
129 break;
[458]130 }
131 if (inst_l == 4)
[453]132 return E_PAR;
133
134 addr_l = init->AddrLength / 4;
[458]135 sil_wrw_mem((uint32_t *)(hspi->base + TOFF_SPI_CTRLR0), (init->WorkMode << hspi->work_mode_offset) |
[453]136 (init->FrameFormat << hspi->frf_offset) | ((init->DataSize - 1) << hspi->dfs_offset));
[458]137 sil_wrw_mem((uint32_t *)(hspi->base + TOFF_SPI_SPI_CTRLR0),
138 ((init->WaitCycles << 11) | (inst_l << 8) | (addr_l << 2) | init->IATransMode));
139 sil_modw_mem((uint32_t *)(hspi->base + TOFF_SPI_CTRLR0), (3 << hspi->tmod_offset), (tmod << hspi->tmod_offset));
[453]140 return E_OK;
141}
142
143/*
144 * DMAコールバック関数
145 */
146static void
147spi_dma_comp(DMA_Handle_t *hdma)
148{
149 SPI_Handle_t *hspi = (SPI_Handle_t *)hdma->localdata;
[458]150 if (hspi != NULL && hspi->Init.semdmaid != 0) {
[453]151 isig_sem(hspi->Init.semdmaid);
152 }
153}
154
155/*
156 * DMA転送開始関数
157 */
158DMA_Handle_t *
159spi_dmac_set_single_mode(SPI_Handle_t *hspi, uint8_t rtx,
[458]160 int8_t ss_no, const void *src, void *dest,
161 uint8_t src_inc, uint8_t dest_inc,
162 uint8_t dmac_burst_size, uint8_t dmac_trans_width,
163 size_t block_size)
[453]164{
165 DMA_Handle_t *hdma;
[458]166 int mem_type_src, mem_type_dest;
167 uint8_t flow_control;
[453]168
[458]169 if (rtx == 0) {
[453]170 hdma = hspi->hdmatx;
[458]171 flow_control = DMA_MEMORY_TO_PERIPH;
[453]172 mem_type_src = 1;
173 mem_type_dest = 0;
174 }
[458]175 else {
[453]176 hdma = hspi->hdmarx;
[458]177 flow_control = DMA_PERIPH_TO_MEMORY;
[453]178 mem_type_src = 0;
179 mem_type_dest = 1;
180 }
[458]181 if (ss_no < 0)
[453]182 ss_no = 0;
183
[458]184 hdma->Init.Direction = flow_control; /* DMA転送方向 */
185 hdma->Init.SrcHandShake = (mem_type_src ? DMAC_HS_SOFTWARE : DMAC_HS_HARDWARE); /* ソースハンドシェイク */
186 hdma->Init.DrcHandShake = (mem_type_dest ? DMAC_HS_SOFTWARE : DMAC_HS_HARDWARE); /* デスティネーションハンドシェイク */
187 hdma->Init.SrcInc = src_inc; /* ソースインクリメント設定 */
188 hdma->Init.DstInc = dest_inc; /* デスティネーションインクリメント設定 */
189 hdma->Init.SrcTransWidth = dmac_trans_width; /* ソース転送幅 */
190 hdma->Init.DstTransWidth = dmac_trans_width; /* デスティネーション転送幅 */
191 hdma->Init.SrcBurstSize = dmac_burst_size; /* ソースバーストサイズ */
192 hdma->Init.DstBurstSize = dmac_burst_size; /* デスティネーションバーストサイズ */
[453]193 dma_reset(hdma);
[458]194 sil_wrw_mem((uint32_t *)(hspi->base + TOFF_SPI_SER), (1 << ss_no));
[453]195 dma_start(hdma, (uintptr_t)src, (uintptr_t)dest, block_size);
196 return hdma;
197}
198
199/*
200 * SPI-DMA転送終了待ち
201 */
202ER
[458]203spi_dmac_wait_done(DMA_Handle_t *hdma)
[453]204{
205 SPI_Handle_t *hspi = (SPI_Handle_t *)hdma->localdata;
206 ER ercd = E_OK;
207 int tick = DMA_TRS_TIMEOUT;
208
[458]209 while ((hdma->status == DMA_STATUS_BUSY) && tick > 0) {
210 if (hspi != NULL && hspi->Init.semdmaid != 0) {
211 ercd = twai_sem(hspi->Init.semdmaid, 5);
[453]212 }
213 else
214 dly_tsk(1);
215 tick--;
216 }
217 dma_end(hdma);
[458]218 if (hdma->ErrorCode != 0)
[453]219 ercd = E_OBJ;
[458]220 else if (tick == 0)
[453]221 ercd = E_TMOUT;
222 return ercd;
223}
224
225/*
226 * SPI内部転送終了待ち
227 */
228ER
229spi_inwait(SPI_Handle_t *hspi, uint32_t timeout)
230{
231 ER ercd = E_OK;
232 int tick = timeout;
233
[458]234 if (hspi->hdmatx != NULL) {
235 sil_wrw_mem((uint32_t *)(hspi->base + TOFF_SPI_IMR), 0x0011);
236 while ((sil_rew_mem((uint32_t *)(hspi->base + TOFF_SPI_SR)) & 0x05) != 0x04 && tick > 0) {
237 if (hspi->Init.semid != 0)
238 twai_sem(hspi->Init.semid, 5);
239 else
240 dly_tsk(1);
241 tick--;
242 }
[453]243 }
[458]244 sil_wrw_mem((uint32_t *)(hspi->base + TOFF_SPI_SER), 0x00000000);
245 sil_wrw_mem((uint32_t *)(hspi->base + TOFF_SPI_SSIENR), SPI_SSIENR_DISABLE);
[453]246
[458]247 if (hspi->ErrorCode != 0)
[453]248 ercd = E_OBJ;
[458]249 else if (tick == 0)
[453]250 ercd = E_TMOUT;
251 hspi->TxXferCount = 0;
252 hspi->RxXferCount = 0;
253 return ercd;
254}
255
256
257/*
258 * SPI初期設定
259 * parameter1 port: SPIポート番号
260 * parameter2 spii: SPI初期設定構造体へのポインタ
261 * return SPIハンドラへのポインタ、NULLでエラー
262 */
263SPI_Handle_t *
264spi_init(ID port, const SPI_Init_t *init)
265{
266 SPI_Handle_t *hspi;
267 DMA_Handle_t *hdma;
268 const SPI_PortControlBlock *spcb;
269 unsigned long base;
[458]270 uint8_t spi_num;
[453]271 uint32_t spi_baudr, clk_th1, threshold;
[458]272 uint8_t dfs_offset, frf_offset, work_mode_offset, tmod_offset;
[453]273 uint32_t dsize_err = 0;
[458]274 uint32_t inst_l = 4;
275 uint32_t addr_l;
[453]276
[458]277 if (port < SPI1_PORTID || port > NUM_SPIPORT)
[453]278 return NULL;
279 spi_num = INDEX_SPI(port);
[458]280 if (init == NULL)
[453]281 return NULL;
[458]282 if (init->DataSize < 4 && init->DataSize > 32)
[453]283 return NULL;
[458]284 if (init->AddrLength % 4 != 0 && init->AddrLength > 60)
[453]285 return NULL;
286
287 /*
288 * クロック設定
289 */
[458]290 if (spi_num == 3) {
291 sil_orw_mem((uint32_t *)(TADR_SYSCTL_BASE + TOFF_CLK_SEL0), SYSCTL_CLK_SEL0_SPI3_CLK_SEL);
[453]292 }
[458]293 if (spi_num < 2)
294 sil_orw_mem((uint32_t *)(TADR_SYSCTL_BASE + TOFF_SYSCTL_CLK_EN_CENT), SYSCTL_CLK_EN_CENT_APB2_CLK_EN);
295 else if (spi_num == 2)
296 sil_orw_mem((uint32_t *)(TADR_SYSCTL_BASE + TOFF_SYSCTL_CLK_EN_CENT), SYSCTL_CLK_EN_CENT_APB0_CLK_EN);
297 sil_orw_mem((uint32_t *)(TADR_SYSCTL_BASE + TOFF_SYSCTL_CLK_EN_PERI), (SYSCTL_CLK_EN_PERI_SPI0_CLK_EN << spi_num));
298 sil_andw_mem((uint32_t *)(TADR_SYSCTL_BASE + TOFF_SYSCTL_CLK_TH1), 0xFF << (spi_num * 8));
[453]299
300 /*
301 * ピンファンクション設定
302 */
303 spcb = &spi_pcb[spi_num];
[458]304 if (spcb->func_ss >= 0 && init->SsPin >= 0)
[453]305 fpioa_set_function(init->SsPin, (uint8_t)(spcb->func_ss + init->SsNo));
[458]306 if (spcb->func_sclk >= 0 && init->SclkPin >= 0)
[453]307 fpioa_set_function(init->SclkPin, (uint8_t)(spcb->func_sclk));
[458]308 if (spcb->func_data >= 0) {
309 if (init->MosiPin >= 0)
[453]310 fpioa_set_function(init->MosiPin, (uint8_t)(spcb->func_data));
[458]311 if (init->MisoPin >= 0)
312 fpioa_set_function(init->MisoPin, (uint8_t)(spcb->func_data + 1));
[453]313 }
314 hspi = &SpiHandle[spi_num];
315 base = spcb->base;
316
[458]317 switch (spi_num) {
[453]318 case 0:
319 case 1:
320 dfs_offset = 16;
321 frf_offset = 21;
322 work_mode_offset = 6;
323 tmod_offset = 8;
324 break;
325 case 3:
326 default:
327 dfs_offset = 0;
328 frf_offset = 22;
329 work_mode_offset = 8;
330 tmod_offset = 10;
331 break;
332 }
333
[458]334 switch (init->FrameFormat) {
[453]335 case SPI_FF_DUAL:
[458]336 if (init->DataSize % 2 != 0)
[453]337 dsize_err = 1;
338 break;
339 case SPI_FF_QUAD:
[458]340 if (init->DataSize % 4 != 0)
[453]341 dsize_err = 1;
342 break;
343 case SPI_FF_OCTAL:
[458]344 if (init->DataSize % 8 != 0)
[453]345 dsize_err = 1;
346 break;
347 default:
348 break;
349 }
350
[458]351 switch (init->InstLength) {
[453]352 case 0:
353 inst_l = 0;
354 break;
355 case 4:
356 inst_l = 1;
357 break;
358 case 8:
359 inst_l = 2;
360 break;
361 case 16:
362 inst_l = 3;
363 break;
364 default:
365 break;
366 }
[458]367 if (inst_l == 4 || dsize_err) {
[453]368 syslog_0(LOG_ERROR, "Invalid instruction length");
369 return NULL;
370 }
371 addr_l = init->AddrLength / 4;
372
373 memcpy(&hspi->Init, init, sizeof(SPI_Init_t));
374
[458]375 if (sil_rew_mem((uint32_t *)(base + TOFF_SPI_BAUDR)) == 0)
376 sil_wrw_mem((uint32_t *)(base + TOFF_SPI_BAUDR), 0x14);
[453]377 /*
378 * 割込み不許可
379 */
[458]380 sil_wrw_mem((uint32_t *)(base + TOFF_SPI_IMR), 0x00000000);
[453]381
[458]382 sil_wrw_mem((uint32_t *)(base + TOFF_SPI_DMACR), 0x00000000);
383 sil_wrw_mem((uint32_t *)(base + TOFF_SPI_DMATDLR), 0x00000010);
384 sil_wrw_mem((uint32_t *)(base + TOFF_SPI_DMARDLR), 0x00000000);
385 sil_wrw_mem((uint32_t *)(base + TOFF_SPI_SER), 0x00000000);
386 sil_wrw_mem((uint32_t *)(base + TOFF_SPI_SSIENR), SPI_SSIENR_DISABLE);
387 sil_wrw_mem((uint32_t *)(base + TOFF_SPI_CTRLR0), (init->WorkMode << work_mode_offset) |
[453]388 (init->FrameFormat << frf_offset) | ((init->DataSize - 1) << dfs_offset));
[458]389 sil_wrw_mem((uint32_t *)(base + TOFF_SPI_SPI_CTRLR0),
[453]390 ((init->WaitCycles << 11) | (inst_l << 8) | (addr_l << 2) | init->IATransMode));
[458]391 sil_wrw_mem((uint32_t *)(base + TOFF_SPI_ENDIAN), init->SignBit);
[453]392
393 /*
394 * 転送クロック設定
395 */
[458]396 clk_th1 = sil_rew_mem((uint32_t *)(TADR_SYSCTL_BASE + TOFF_SYSCTL_CLK_TH1));
[453]397 threshold = (clk_th1 >> (spi_num * 8)) & 0xff;
398 spi_baudr = (get_pll_clock(0) / ((threshold + 1) * 2)) / init->Prescaler;
399
[458]400 if (spi_baudr < 2) {
[453]401 spi_baudr = 2;
402 }
[458]403 else if (spi_baudr > 65534) {
[453]404 spi_baudr = 65534;
405 }
[458]406 sil_wrw_mem((uint32_t *)(base + TOFF_SPI_BAUDR), spi_baudr);
[453]407
408 /*
409 * ハンドラ初期化
410 */
411 hspi->base = base;
412 hspi->spi_num = spi_num;
[458]413 hspi->dfs_offset = dfs_offset;
414 hspi->frf_offset = frf_offset;
[453]415 hspi->work_mode_offset = work_mode_offset;
416 hspi->tmod_offset = tmod_offset;
417 hspi->hdmatx = NULL;
418 hspi->hdmarx = NULL;
[458]419 if (init->TxDMAChannel >= 0) {
[453]420 hdma = &spi_dma_handle[init->TxDMAChannel][0];
421 hdma->chnum = init->TxDMAChannel;
[458]422 if (init->RxDMAChannel >= 0)
423 hdma->xfercallback = NULL;
[453]424 else
[458]425 hdma->xfercallback = spi_dma_comp;
426 hdma->errorcallback = NULL;
427 hdma->Init.Request = DMA_SELECT_SSI0_TX_REQ + spi_num * 2; /* DMA選択 */
428 hdma->Init.Direction = DMA_MEMORY_TO_PERIPH; /* DMA転送方向 */
429 hdma->Init.SrcMultBlock = DMAC_MULTBLOCK_CONT; /* ソースマルチブロックタイプ */
430 hdma->Init.DrcMultBlock = DMAC_MULTBLOCK_CONT; /* デスティネーションマルチブロックタイプ */
431 hdma->Init.SrcHandShake = DMAC_HS_SOFTWARE; /* ソースハンドシェイク */
432 hdma->Init.DrcHandShake = DMAC_HS_HARDWARE; /* デスティネーションハンドシェイク */
433 hdma->Init.SrcHwhsPol = DMAC_HWHS_POLARITY_LOW; /* ソースハードウェアハンドシェイク極性 */
434 hdma->Init.DrcHwhsPol = DMAC_HWHS_POLARITY_LOW; /* デスティネーションハードウェアハンドシェイク極性 */
435 hdma->Init.Priority = 4; /* 優先度 */
436 hdma->Init.SrcMaster = DMAC_MASTER1; /* ソースマスター設定 */
437 hdma->Init.DstMaster = DMAC_MASTER2; /* デスティネーションマスター設定 */
438 hdma->Init.SrcInc = DMAC_ADDR_INCREMENT; /* ソースインクリメント設定 */
439 hdma->Init.DstInc = DMAC_ADDR_NOCHANGE; /* デスティネーションインクリメント設定 */
440 hdma->Init.SrcTransWidth = DMAC_TRANS_WIDTH_32; /* ソース転送幅 */
441 hdma->Init.DstTransWidth = DMAC_TRANS_WIDTH_32; /* デスティネーション転送幅 */
442 hdma->Init.SrcBurstSize = DMAC_MSIZE_4; /* ソースバーストサイズ */
443 hdma->Init.DstBurstSize = DMAC_MSIZE_4; /* デスティネーションバーストサイズ */
444 hdma->Init.IocBlkTrans = 0; /* IOCブロック転送 */
445 hdma->localdata = (void *)hspi;
[453]446 dma_init(hdma);
447 hspi->hdmatx = hdma;
448 }
[458]449 if (init->RxDMAChannel >= 0) {
[453]450 hdma = &spi_dma_handle[init->RxDMAChannel][1];
451 hdma->chnum = init->RxDMAChannel;
[458]452 hdma->xfercallback = spi_dma_comp;
453 hdma->errorcallback = NULL;
454 hdma->Init.Request = DMA_SELECT_SSI0_RX_REQ + spi_num * 2; /* DMA選択 */
455 hdma->Init.Direction = DMA_PERIPH_TO_MEMORY; /* DMA転送方向 */
456 hdma->Init.SrcMultBlock = DMAC_MULTBLOCK_CONT; /* ソースマルチブロックタイプ */
457 hdma->Init.DrcMultBlock = DMAC_MULTBLOCK_CONT; /* デスティネーションマルチブロックタイプ */
458 hdma->Init.SrcHandShake = DMAC_HS_HARDWARE; /* ソースハンドシェイク */
459 hdma->Init.DrcHandShake = DMAC_HS_SOFTWARE; /* デスティネーションハンドシェイク */
460 hdma->Init.SrcHwhsPol = DMAC_HWHS_POLARITY_LOW; /* ソースハードウェアハンドシェイク極性 */
461 hdma->Init.DrcHwhsPol = DMAC_HWHS_POLARITY_LOW; /* デスティネーションハードウェアハンドシェイク極性 */
462 hdma->Init.Priority = 4; /* 優先度 */
463 hdma->Init.SrcMaster = DMAC_MASTER1; /* ソースマスター設定 */
464 hdma->Init.DstMaster = DMAC_MASTER2; /* デスティネーションマスター設定 */
465 hdma->Init.SrcInc = DMAC_ADDR_NOCHANGE; /* ソースインクリメント設定 */
466 hdma->Init.DstInc = DMAC_ADDR_INCREMENT; /* デスティネーションインクリメント設定 */
467 hdma->Init.SrcTransWidth = DMAC_TRANS_WIDTH_32; /* ソース転送幅 */
468 hdma->Init.DstTransWidth = DMAC_TRANS_WIDTH_32; /* デスティネーション転送幅 */
469 hdma->Init.SrcBurstSize = DMAC_MSIZE_4; /* ソースバーストサイズ */
470 hdma->Init.DstBurstSize = DMAC_MSIZE_4; /* デスティネーションバーストサイズ */
471 hdma->Init.IocBlkTrans = 0; /* IOCブロック転送 */
472 hdma->localdata = (void *)hspi;
[453]473 dma_init(hdma);
474 hspi->hdmarx = hdma;
475 }
476 hspi->status = SPI_STATUS_READY;
[458]477 hspi->xmode = 0;
[453]478 return hspi;
479}
480
481/*
482 * SPI終了設定
483 * parameter1 hspi: SPIハンドラへのポインタ
484 * return ERコード
485 */
486ER
487spi_deinit(SPI_Handle_t *hspi)
488{
[458]489 if (hspi == NULL)
[453]490 return E_PAR;
491
[458]492 if (hspi->hdmatx != NULL) {
[453]493 dma_deinit(hspi->hdmatx);
494 hspi->hdmatx = NULL;
495 }
[458]496 if (hspi->hdmarx != NULL) {
[453]497 dma_deinit(hspi->hdmarx);
498 hspi->hdmarx = NULL;
499 }
[458]500 sil_wrw_mem((uint32_t *)(hspi->base + TOFF_SPI_SSIENR), SPI_SSIENR_DISABLE);
[453]501
502 hspi->ErrorCode = SPI_ERROR_NONE;
503 hspi->status = SPI_STATUS_RESET;
504 return E_OK;
505}
506
507/*
508 * ポーリングデータ送信
509 */
510static void
[458]511spi_send_data_normal(SPI_Handle_t *hspi, int8_t ss_no, const uint8_t *tx_buff, size_t tx_len)
[453]512{
[458]513 size_t fifo_len;
514 const uint32_t *src = (const uint32_t *)tx_buff;
515
516 if (ss_no < 0)
517 ss_no = 0;
518
519 sil_wrw_mem((uint32_t *)(hspi->base + TOFF_SPI_SSIENR), SPI_SSIENR_ENABLE);
520 sil_wrw_mem((uint32_t *)(hspi->base + TOFF_SPI_SER), (1 << ss_no));
521 while (tx_len > 0) {
522 fifo_len = 32 - sil_rew_mem((uint32_t *)(hspi->base + TOFF_SPI_TXFLR));
523 fifo_len = fifo_len < tx_len ? fifo_len : tx_len;
524 uint32_t *dst = (uint32_t *)(hspi->base + TOFF_SPI_DR);
525 uint32_t *end = &dst[fifo_len];
526 for (; dst < end; src++, dst++) {
527 sil_wrw_mem(dst, *src);
528 }
529 tx_len -= fifo_len;
530
531 int tick = 200;
532 //sil_wrw_mem((uint32_t *)(hspi->base+TOFF_SPI_IMR), 0x0011);
533 while ((sil_rew_mem((uint32_t *)(hspi->base + TOFF_SPI_SR)) & 0x05) != 0x04 && tick > 0) {
534 //if(hspi->Init.semid != 0)
535 // twai_sem(hspi->Init.semid, 1);
536 //else
537 // dly_tsk(1);
538 tick--;
539 }
540 }
541}
542
543/*
544 * ポーリングデータ送信
545 */
546static void
547spi_send_data_normal2(SPI_Handle_t *hspi, int8_t ss_no, uint32_t tx_data, size_t tx_len)
548{
549 size_t fifo_len;
[453]550 uint8_t frame_width = get_framewidth(hspi->Init.DataSize);
551
[458]552 switch (frame_width)
553 {
554 case 2:
555 tx_data = (tx_data << 16) | (tx_data & 0xFFFF);
556 break;
557 case 1:
558 tx_data = (tx_data << 24) | ((tx_data << 16) & 0xFF0000) | ((tx_data << 8) & 0xFF00) | (tx_data & 0xFF);
559 break;
[453]560 }
[458]561
562 if (ss_no < 0)
[453]563 ss_no = 0;
564
[458]565 sil_wrw_mem((uint32_t *)(hspi->base + TOFF_SPI_SSIENR), SPI_SSIENR_ENABLE);
566 sil_wrw_mem((uint32_t *)(hspi->base + TOFF_SPI_SER), (1 << ss_no));
567 while (tx_len > 0) {
568 fifo_len = 32 - sil_rew_mem((uint32_t *)(hspi->base + TOFF_SPI_TXFLR));
[453]569 fifo_len = fifo_len < tx_len ? fifo_len : tx_len;
[458]570 uint32_t *dst = (uint32_t *)(hspi->base + TOFF_SPI_DR);
571 uint32_t *end = &dst[fifo_len];
572 for (; dst < end; dst++) {
573 sil_wrw_mem(dst, tx_data);
574 }
[453]575 tx_len -= fifo_len;
[458]576
577 int tick = 200;
578 //sil_wrw_mem((uint32_t *)(hspi->base+TOFF_SPI_IMR), 0x0011);
579 while ((sil_rew_mem((uint32_t *)(hspi->base + TOFF_SPI_SR)) & 0x05) != 0x04 && tick > 0) {
580 //if(hspi->Init.semid != 0)
581 // twai_sem(hspi->Init.semid, 1);
582 //else
583 // dly_tsk(1);
584 tick--;
585 }
[453]586 }
587}
588
589/*
590 * SPI送信実行関数
591 * parameter1 hspi: SPIハンドラへのポインタ
592 * parameter2 ss_no: SS番号
593 * parameter3 pdata: 送信バッファへのポインタ
594 * parameter4 length: 送信サイズ
595 * return ERコード
596 */
597ER
598spi_core_transmit(SPI_Handle_t *hspi, int8_t ss_no, uint8_t *pdata, uint16_t length)
599{
600 DMA_Handle_t *hdma;
601 ER ercd = E_OK;
602
[458]603 if (hspi == NULL)
[453]604 return E_PAR;
605
[458]606 if (hspi->Init.semlock != 0)
[453]607 wai_sem(hspi->Init.semlock);
[458]608
[453]609 hspi->xmode = SPI_XMODE_TX;
[458]610 spi_set_tmod(hspi, SPI_TMOD_TRANS);
611 if (hspi->hdmatx != NULL) {
612 sil_wrw_mem((uint32_t *)(hspi->base + TOFF_SPI_DMACR), SPI_DMACR_TXENABLE);
613 sil_wrw_mem((uint32_t *)(hspi->base + TOFF_SPI_SSIENR), SPI_SSIENR_ENABLE);
614 hdma = spi_dmac_set_single_mode(hspi, 0, ss_no, (const void *)pdata,
615 (void *)(hspi->base + TOFF_SPI_DR), DMAC_ADDR_INCREMENT, DMAC_ADDR_NOCHANGE,
616 DMAC_MSIZE_4, DMAC_TRANS_WIDTH_32, length);
[453]617 spi_dmac_wait_done(hdma);
618 }
[458]619 else {
620 spi_send_data_normal(hspi, ss_no, (const void *)pdata, length);
[453]621 }
622
623#if SPI_WAIT_TIME != 0
624 ercd = spi_inwait(hspi, SPI_WAIT_TIME * length);
625
[458]626 if (hspi->Init.semlock != 0)
[453]627 sig_sem(hspi->Init.semlock);
628#endif
629 return ercd;
630}
631
632/*
633 * SPIフィル送信実行関数
634 * parameter1 hspi: SPIハンドラへのポインタ
635 * parameter2 ss_no: SS番号
636 * parameter3 pdata: 送信バッファへのポインタ
637 * parameter4 length: 送信サイズ
638 * return ERコード
639 */
640ER
641spi_core_transmit_fill(SPI_Handle_t *hspi, int8_t ss_no, const uint32_t *tx_buff, size_t tx_len)
642{
643 DMA_Handle_t *hdmatx;
644 ER ercd = E_OK;
645
[458]646 if (hspi == NULL)
[453]647 return E_PAR;
648
[458]649 if (hspi->Init.semlock != 0)
[453]650 wai_sem(hspi->Init.semlock);
651
652 hspi->xmode = SPI_XMODE_TX;
653 spi_set_tmod(hspi, SPI_TMOD_TRANS);
[458]654 if (hspi->hdmatx != NULL) {
655 sil_wrw_mem((uint32_t *)(hspi->base + TOFF_SPI_DMACR), SPI_DMACR_TXENABLE);
656 sil_wrw_mem((uint32_t *)(hspi->base + TOFF_SPI_SSIENR), SPI_SSIENR_ENABLE);
[453]657
[458]658 hdmatx = spi_dmac_set_single_mode(hspi, 0, ss_no, tx_buff,
659 (void *)(hspi->base + TOFF_SPI_DR), DMAC_ADDR_NOCHANGE, DMAC_ADDR_NOCHANGE,
660 DMAC_MSIZE_1, DMAC_TRANS_WIDTH_32, tx_len);
661 spi_dmac_wait_done(hdmatx);
662 }
663 else {
664 spi_send_data_normal2(hspi, ss_no, *tx_buff, tx_len);
665 }
[453]666#if SPI_WAIT_TIME != 0
667 ercd = spi_inwait(hspi, SPI_WAIT_TIME * tx_len);
668
[458]669 if (hspi->Init.semlock != 0)
[453]670 sig_sem(hspi->Init.semlock);
671#endif
672 return ercd;
673}
674
675/*
676 * SPI受信実行関数
677 * parameter1 hspi: SPIハンドラへのポインタ
678 * parameter2 ss_no: SS番号
679 * parameter3 pdata: 受信バッファへのポインタ
680 * parameter4 length: 受信サイズ
681 * return ERコード
682 */
683ER
684spi_core_receive(SPI_Handle_t *hspi, int8_t ss_no, void *rx_buff, size_t rx_len)
685{
[458]686 DMA_Handle_t *hdmarx;
[453]687 ER ercd = E_OK;
688
[458]689 if (hspi == NULL || hspi->spi_num == 2)
[453]690 return E_PAR;
691
[458]692 if (hspi->Init.semlock != 0)
[453]693 wai_sem(hspi->Init.semlock);
694
695 hspi->xmode = SPI_XMODE_RX;
696 spi_set_tmod(hspi, SPI_TMOD_RECV);
697
[458]698 sil_wrw_mem((uint32_t *)(hspi->base + TOFF_SPI_CTRLR1), (rx_len - 1));
699 sil_wrw_mem((uint32_t *)(hspi->base + TOFF_SPI_DMACR), SPI_DMACR_RXENABLE);
700 sil_wrw_mem((uint32_t *)(hspi->base + TOFF_SPI_SSIENR), SPI_SSIENR_ENABLE);
[453]701
[458]702 hdmarx = spi_dmac_set_single_mode(hspi, 1, ss_no,
703 (void *)(hspi->base + TOFF_SPI_DR), rx_buff, DMAC_ADDR_NOCHANGE, DMAC_ADDR_INCREMENT,
704 DMAC_MSIZE_1, DMAC_TRANS_WIDTH_32, rx_len);
705 if (hspi->Init.FrameFormat == SPI_FF_STANDARD)
706 sil_wrw_mem((uint32_t *)(hspi->base + TOFF_SPI_DR), 0xFFFFFFFF);
707 spi_dmac_wait_done(hdmarx);
[453]708
[458]709 sil_wrw_mem((uint32_t *)(hspi->base + TOFF_SPI_SER), 0x00000000);
710 sil_wrw_mem((uint32_t *)(hspi->base + TOFF_SPI_SSIENR), SPI_SSIENR_DISABLE);
[453]711
712#if SPI_WAIT_TIME != 0
713 ercd = spi_inwait(hspi, SPI_WAIT_TIME * rx_len);
714
[458]715 if (hspi->Init.semlock != 0)
[453]716 sig_sem(hspi->Init.semlock);
717#endif
718 return ercd;
719}
720
721/*
722 * SPI送受信実行関数
723 * parameter1 hspi: SPIハンドラへのポインタ
724 * parameter2 ss_no: SS番号
725 * parameter3 ptxdata: 送信バッファへのポインタ
726 * parameter4 prxdata: 受信バッファへのポインタ
727 * parameter5 length: 送受信サイズ
728 * return ERコード
729 */
730ER
731spi_core_transrecv(SPI_Handle_t *hspi, int8_t ss_no, const uint8_t *tx_buf, uint8_t *rx_buf, size_t len)
732{
[458]733 DMA_Handle_t *hdmarx, *hdmatx;
734 uint8_t frame_width = get_framewidth(hspi->Init.DataSize);
735 size_t v_len = len / frame_width;
[453]736 ER ercd = E_OK;
737
[458]738 if (hspi == NULL)
[453]739 return E_PAR;
740
[458]741 if (hspi->Init.semlock != 0)
[453]742 wai_sem(hspi->Init.semlock);
743
744 hspi->xmode = SPI_XMODE_TXRX;
[458]745 spi_set_tmod(hspi, SPI_TMOD_TRANS_RECV);
[453]746
[458]747 if (hspi->hdmatx != NULL) {
748 sil_wrw_mem((uint32_t *)(hspi->base + TOFF_SPI_DMACR), (SPI_DMACR_TXENABLE | SPI_DMACR_RXENABLE));
749 sil_wrw_mem((uint32_t *)(hspi->base + TOFF_SPI_SSIENR), SPI_SSIENR_ENABLE);
[453]750
[458]751 hdmarx = spi_dmac_set_single_mode(hspi, 1, ss_no, (void *)(hspi->base + TOFF_SPI_DR), rx_buf, DMAC_ADDR_NOCHANGE, DMAC_ADDR_INCREMENT,
752 DMAC_MSIZE_1, DMAC_TRANS_WIDTH_32, v_len);
753 hdmatx = spi_dmac_set_single_mode(hspi, 0, -1, tx_buf, (void *)(hspi->base + TOFF_SPI_DR), DMAC_ADDR_INCREMENT, DMAC_ADDR_NOCHANGE,
754 DMAC_MSIZE_4, DMAC_TRANS_WIDTH_32, v_len);
[453]755
[458]756 spi_dmac_wait_done(hdmatx);
[453]757 }
[458]758 else {
759 sil_wrw_mem((uint32_t *)(hspi->base + TOFF_SPI_DMACR), SPI_DMACR_RXENABLE);
760 sil_wrw_mem((uint32_t *)(hspi->base + TOFF_SPI_SSIENR), SPI_SSIENR_ENABLE);
[453]761
[458]762 hdmarx = spi_dmac_set_single_mode(hspi, 1, ss_no,
763 (void *)(hspi->base + TOFF_SPI_DR), rx_buf, DMAC_ADDR_NOCHANGE, DMAC_ADDR_INCREMENT,
764 DMAC_MSIZE_1, DMAC_TRANS_WIDTH_32, v_len);
765 spi_send_data_normal(hspi, -1, (const void *)tx_buf, len);
[453]766 }
767 spi_dmac_wait_done(hdmarx);
768
[458]769 sil_wrw_mem((uint32_t *)(hspi->base + TOFF_SPI_SER), 0x00000000);
770 sil_wrw_mem((uint32_t *)(hspi->base + TOFF_SPI_SSIENR), SPI_SSIENR_DISABLE);
[453]771
772#if SPI_WAIT_TIME != 0
773 ercd = spi_inwait(hspi, SPI_WAIT_TIME * len);
774
[458]775 if (hspi->Init.semlock != 0)
[453]776 sig_sem(hspi->Init.semlock);
777#endif
778 return ercd;
779}
780
781/*
782 * SPI転送終了待ち
783 */
784ER
785spi_wait(SPI_Handle_t *hspi, uint32_t timeout)
786{
787 ER ercd = E_OK;
788
789#if SPI_WAIT_TIME == 0
[458]790 if (hspi == NULL)
[453]791 return E_PAR;
792 ercd = spi_inwait(hspi, timeout);
[458]793 if (hspi->Init.semlock != 0)
[453]794 sig_sem(hspi->Init.semlock);
795#endif
796 return ercd;
797}
798
799/*
800 * SPI割込みサービスルーチン
801 */
802void
803spi_handler(SPI_Handle_t *hspi)
804{
[458]805 //volatile uint32_t imr, isr;
806 volatile uint32_t tmp;
[453]807
[458]808 //imr = sil_rew_mem((uint32_t *)(hspi->base+TOFF_SPI_IMR));
809 //isr = sil_rew_mem((uint32_t *)(hspi->base+TOFF_SPI_ISR));
810 sil_wrw_mem((uint32_t *)(hspi->base + TOFF_SPI_IMR), 0);
[453]811
[458]812 //syslog_2(LOG_DEBUG, "spi_handler imr[%08x] isr[%08x]", imr, isr);
813 tmp = sil_rew_mem((uint32_t *)(hspi->base + TOFF_SPI_ICR));
814 if (hspi->Init.semid != 0)
[453]815 isig_sem(hspi->Init.semid);
816 (void)(tmp);
817}
818
819/*
820 * SPI割込みサービスルーチン
821 */
822void spi_isr(intptr_t exinf)
823{
[458]824 spi_handler(&SpiHandle[INDEX_SPI((uint32_t)exinf)]);
[453]825}
Note: See TracBrowser for help on using the repository browser.