source: azure_iot_hub_f767zi/trunk/asp_baseplatform/pdic/stm32f7xx/qspi.c

Last change on this file 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: 32.1 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 * QSPIドライバ関数群
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 "qspi.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#define MIN(a, b) ((a) > (b) ? (b) : (a))
60
61/*
62 * QSPIポートIDから管理ブロックを取り出すためのマクロ
63 */
64#define INDEX_QSPI(qspiid) ((uint_t)((qspiid) - 1))
65
66#define GPIO_AF9_QUADSPI ((uint8_t)0x09) /* QUADSPI Alternate Function mapping */
67#define GPIO_AF10_QUADSPI ((uint8_t)0x0A) /* QUADSPI Alternate Function mapping */
68
69#ifndef QSPI_WRITE_SIZE
70#define QSPI_WRITE_SIZE 256
71#endif
72#define QPSI_TIMEOUT_DEFAULT_VALUE (5000) /* 5sec */
73
74/*
75 * QSPI通信レジスタ設定ファンクション定義
76 */
77#define QSPI_FUNCTIONAL_MODE_INDIRECT_WRITE 0x00000000 /* Indirect write mode*/
78#define QSPI_FUNCTIONAL_MODE_INDIRECT_READ QUADSPI_CCR_FMODE_0 /* Indirect read mode*/
79#define QSPI_FUNCTIONAL_MODE_AUTO_POLLING QUADSPI_CCR_FMODE_1 /* Automatic polling mode*/
80#define QSPI_FUNCTIONAL_MODE_MEMORY_MAPPED QUADSPI_CCR_FMODE /* Memory-mapped mode*/
81
82static const QSPI_PortControlBlock qspi_pcb[NUM_QSPIPORT] = {
83 { TADR_QSPI_R_BASE, (TADR_RCC_BASE+TOFF_RCC_AHB1ENR),
84 RCC_AHB1ENR_GPIOBEN, TADR_GPIOB_BASE, 6, GPIO_AF10_QUADSPI,
85 RCC_AHB1ENR_GPIOBEN, TADR_GPIOB_BASE, 2, GPIO_AF9_QUADSPI,
86 RCC_AHB1ENR_GPIOCEN, TADR_GPIOC_BASE, 9, GPIO_AF9_QUADSPI,
87 RCC_AHB1ENR_GPIOCEN, TADR_GPIOC_BASE, 10, GPIO_AF9_QUADSPI,
88 RCC_AHB1ENR_GPIOEEN, TADR_GPIOE_BASE, 2, GPIO_AF9_QUADSPI,
89 RCC_AHB1ENR_GPIODEN, TADR_GPIOD_BASE, 13, GPIO_AF9_QUADSPI
90 }
91};
92
93QSPI_Handle_t QSPIHandle[NUM_QSPIPORT];
94
95/*
96 * QSPIフラグセット待ち関数
97 * parameter1 hi2c I2Cハンドラへのポインタ
98 * parameter2 flag フラグ値
99 * parameter3 result 最終フラグ値
100 * parameter4 timeout タイムアウト値(ms)
101 * parameter5 ptimout タイムアウト値設定領域
102 * result E_OKで正常終了
103 */
104static ER
105qspi_waitflag(QSPI_Handle_t *hqspi, uint32_t flag, uint32_t result, uint32_t timeout, uint32_t *ptimeout)
106{
107 uint32_t tick = 0;
108
109 while((sil_rew_mem((uint32_t *)(hqspi->base+TOFF_QUADSPI_SR)) & flag) != result){
110 if(tick > timeout){
111 hqspi->errorcode |= QSPI_ERROR_TIMEOUT;
112 return E_TMOUT;
113 }
114 tick++;
115 dly_tsk(1);
116 }
117 *ptimeout -= tick;
118 return E_OK;
119}
120
121/*
122 * QSPIイベント待ち
123 * parameter1 hi2c I2Cハンドラへのポインタ
124 * parameter2 status 変化待ちステータス値
125 * parameter3 timeout タイムアウト値(ms)
126 * result E_OKで正常終了
127 */
128static ER
129qspi_eventwait(QSPI_Handle_t *hqspi, uint32_t status, uint32_t timeout)
130{
131 uint32_t tick = 0;
132
133 while(hqspi->status == status){
134 if(hqspi->semid != 0)
135 twai_sem(hqspi->semid, 1);
136 else
137 dly_tsk(1);
138 tick++;
139 if(tick > timeout)
140 return E_TMOUT;
141 }
142 if(hqspi->errorcode != QSPI_ERROR_NONE)
143 return E_SYS;
144 else
145 return E_OK;
146}
147
148/*
149 * QSPIデバイスのリセット
150 * parameter1 hqspi QSPIハンドラへのポインタ
151 * return 正常終了時、E_OK
152 */
153static ER
154qspi_reinit(QSPI_Handle_t *hqspi)
155{
156 QSPI_Init_t *pini = &hqspi->Init;
157 ER ercd = E_OK;
158 uint32_t timeout = hqspi->timeout;
159 uint32_t i, temp;
160
161 /*
162 * FIFOスレッシュホールド設定
163 */
164 sil_modw_mem((uint32_t *)(hqspi->base+TOFF_QUADSPI_CR), QUADSPI_CR_FTHRES, (pini->fifothreshold - 1) << 8);
165
166 /*
167 * Ready待ち
168 */
169 if((ercd = qspi_waitflag(hqspi, QUADSPI_SR_BUSY, 0, timeout, &timeout)) != E_OK)
170 return ercd;
171
172 /*
173 * QSPI CR設定
174 */
175 temp = sil_rew_mem((uint32_t *)(hqspi->base+TOFF_QUADSPI_CR));
176 temp &= ~(QUADSPI_CR_PRESCALER | QUADSPI_CR_SSHIFT);
177 temp |= (pini->clockprescaler << 24) | pini->sampleshift;
178#ifdef QUADSPI_CR_FSEL
179 temp &= ~QUADSPI_CR_FSEL;
180 temp |= pini->flashid;
181#endif
182#ifdef QUADSPI_CR_DFM
183 temp &= ~QUADSPI_CR_DFM;
184 temp |= pini->dualflash;
185#endif
186 sil_wrw_mem((uint32_t *)(hqspi->base+TOFF_QUADSPI_CR), temp);
187
188 /*
189 * QSPI DCR設定
190 */
191
192 for(i = 0 ; i < 32 ; i++){
193 if((pini->device_size & (1<<i)) != 0)
194 break;
195 }
196 temp = sil_rew_mem((uint32_t *)(hqspi->base+TOFF_QUADSPI_DCR));
197 temp &= ~(QUADSPI_DCR_FSIZE | QUADSPI_DCR_CSHT | QUADSPI_DCR_CKMODE);
198 temp |= (i << 16) | pini->chipselecthightime | pini->clockmode;
199 sil_wrw_mem((uint32_t *)(hqspi->base+TOFF_QUADSPI_DCR), temp);
200
201
202 /*
203 * QSPIイネーブル
204 */
205 sil_orw_mem((uint32_t *)(hqspi->base+TOFF_QUADSPI_CR), QUADSPI_CR_EN);
206
207 /*
208 * QSPIハンドラ設定
209 */
210 hqspi->errorcode = QSPI_ERROR_NONE;
211 hqspi->status = QSPI_STATUS_READY;
212 return E_OK;
213}
214
215
216/*
217 * QSPI通信レジスタ設定
218 * parameter1 hqspi QSPIハンドラへのポインタ
219 * parameter2 cmd コマンドタイプ構造体へのポインタ
220 * parameter3 fmode ファンクションモード
221 * return 正常終了時、E_OK
222 */
223static void
224qspi_config(QSPI_Handle_t *hqspi, QSPI_Command_t *cmd, uint32_t fmode)
225{
226 QSPI_Init_t *pini = &hqspi->Init;
227 uint32_t instruction, alternatebytessize;
228 if(cmd->DataMode != QSPI_DATA_NONE && fmode != QSPI_FUNCTIONAL_MODE_MEMORY_MAPPED){
229 /*
230 * DLRレジスタ設定
231 */
232 sil_wrw_mem((uint32_t *)(hqspi->base+TOFF_QUADSPI_DLR), (cmd->NbData - 1));
233 }
234
235 if(cmd->InstructionMode != QSPI_INSTRUCTION_NONE)
236 instruction = cmd->Instruction;
237 else
238 instruction = 0;
239
240 if(cmd->AlternateByteMode != QSPI_ALTERNATE_BYTES_NONE)
241 alternatebytessize = cmd->AlternateBytesSize;
242 else
243 alternatebytessize = 0;
244
245 /*
246 * ABRレジスタ設定
247 */
248 sil_wrw_mem((uint32_t *)(hqspi->base+TOFF_QUADSPI_ABR), cmd->AlternateBytes);
249
250 if (cmd->AddressMode != QSPI_ADDRESS_NONE){
251 /*
252 * アドレス設定あり、CCR設定
253 */
254 sil_wrw_mem((uint32_t *)(hqspi->base+TOFF_QUADSPI_CCR),
255 (pini->ddrmode | pini->ddrholdhalfcycle | pini->sioomode |
256 cmd->DataMode | (cmd->DummyCycles << 18) |
257 alternatebytessize | cmd->AlternateByteMode |
258 cmd->AddressSize | cmd->AddressMode | cmd->InstructionMode |
259 instruction | fmode));
260 if (fmode != QSPI_FUNCTIONAL_MODE_MEMORY_MAPPED){
261 /* Configure QSPI: AR register with address value */
262 sil_wrw_mem((uint32_t *)(hqspi->base+TOFF_QUADSPI_AR), cmd->Address);
263 }
264 }
265 else{
266 /*
267 * アドレス設定なし、CCR設定
268 */
269 sil_wrw_mem((uint32_t *)(hqspi->base+TOFF_QUADSPI_CCR),
270 (pini->ddrmode | pini->ddrholdhalfcycle | pini->sioomode |
271 cmd->DataMode | (cmd->DummyCycles << 18) |
272 alternatebytessize | cmd->AlternateByteMode |
273 cmd->AddressMode | cmd->InstructionMode |
274 instruction | fmode));
275 }
276}
277
278/*
279 * QSPIコマンド送信
280 * parameter1 hqspi QSPIハンドラへのポインタ
281 * parameter2 cmd コマンドタイプ構造体へのポインタ
282 * parameter3 timeout タイムアウト時間(ms)
283 * return 正常終了時、E_OK
284 */
285ER
286qspi_command(QSPI_Handle_t *hqspi, QSPI_Command_t *cmd, uint32_t Timeout)
287{
288 ER ercd = E_OK;
289
290 if(cmd->InstructionMode != QSPI_INSTRUCTION_NONE){
291 if(cmd->Instruction > 0xff)
292 return E_PAR;
293 }
294 if(cmd->AddressMode != QSPI_ADDRESS_NONE){
295 if((cmd->AddressSize & ~QUADSPI_CCR_ADSIZE) != 0)
296 return E_PAR;
297 }
298 if(cmd->AlternateByteMode != QSPI_ALTERNATE_BYTES_NONE){
299 if((cmd->AlternateBytesSize & ~QUADSPI_CCR_ABSIZE) != 0)
300 return E_PAR;
301 }
302 if(cmd->DummyCycles > 31)
303 return E_PAR;
304 if((cmd->DataMode & ~QUADSPI_CCR_DMODE) != 0)
305 return E_PAR;
306
307 if(hqspi->status != QSPI_STATUS_READY)
308 return E_OBJ;
309
310 /*
311 * ステータス、エラー初期化
312 */
313 hqspi->errorcode = QSPI_ERROR_NONE;
314 hqspi->status = QSPI_STATUS_BUSY;
315
316 /*
317 * READY待ち
318 */
319 ercd = qspi_waitflag(hqspi, QUADSPI_SR_BUSY, 0, Timeout, &Timeout);
320 if(ercd != E_OK)
321 return ercd;
322
323 if(cmd->DataMode == QSPI_DATA_NONE){
324 /*
325 * データ転送なしなら、割込みクリア
326 */
327 sil_wrw_mem((uint32_t *)(hqspi->base+TOFF_QUADSPI_FCR), (QUADSPI_FCR_CTEF | QUADSPI_FCR_CTCF));
328 }
329
330 /*
331 * 書込みモード通信レジスタ設定
332 */
333 qspi_config(hqspi, cmd, QSPI_FUNCTIONAL_MODE_INDIRECT_WRITE);
334
335 if(cmd->DataMode == QSPI_DATA_NONE){
336 /*
337 * TCF設定待ち
338 */
339 ercd = qspi_waitflag(hqspi, QUADSPI_SR_TCF, QUADSPI_SR_TCF, Timeout, &Timeout);
340
341 if(ercd == E_OK){
342 sil_orw_mem((uint32_t *)(hqspi->base+TOFF_QUADSPI_CR), (QUADSPI_CR_TEIE | QUADSPI_CR_TCIE));
343
344 /*
345 * QSPI割込み終了待ち
346 */
347 ercd = qspi_eventwait(hqspi, QSPI_STATUS_BUSY, Timeout);
348 }
349 }
350 else /* データ転送ありなら、正常終了 */
351 hqspi->status = QSPI_STATUS_READY;
352 return ercd;
353}
354
355/*
356 * QSPIオートマチック ポーリングモード設定
357 * parameter1 hqspi QSPIハンドラへのポインタ
358 * parameter2 cmd コマンドタイプ構造体へのポインタ
359 * parameter3 cfg オートマチック ポーリングモード設定
360 * parameter4 timeout タイムアウト時間(ms)
361 * return 正常終了時、E_OK
362 */
363ER
364qspi_autopolling(QSPI_Handle_t *hqspi, QSPI_Command_t *cmd, QSPI_AutoPolling_t *cfg, uint32_t Timeout)
365{
366 ER ercd = E_OK;
367
368 if((cmd->InstructionMode & ~QUADSPI_CCR_IMODE) != 0)
369 return E_PAR;
370 if(cmd->InstructionMode != QSPI_INSTRUCTION_NONE && cmd->Instruction > 0xFF)
371 return E_PAR;
372 if((cmd->AddressMode & ~QUADSPI_CCR_ADMODE) != 0)
373 return E_PAR;
374 if(cmd->AddressMode != QSPI_ADDRESS_NONE && (cmd->AddressSize & ~QUADSPI_CCR_ADSIZE) != 0)
375 return E_PAR;
376 if((cmd->AlternateByteMode & ~QUADSPI_CCR_ABMODE) != 0)
377 return E_PAR;
378 if(cmd->AlternateByteMode != QSPI_ALTERNATE_BYTES_NONE && (cmd->AlternateBytesSize & ~QUADSPI_CCR_ABSIZE) != 0)
379 return E_PAR;
380 if(cmd->DummyCycles > 31)
381 return E_PAR;
382 if((cmd->DataMode & ~QUADSPI_CCR_DMODE) != 0)
383 return E_PAR;
384
385 if(cfg->Interval > QUADSPI_PIR_INTERVAL)
386 return E_PAR;
387 if(cfg->StatusBytesSize < 1 || cfg->StatusBytesSize > 4)
388 return E_PAR;
389 if((cfg->MatchMode & ~QUADSPI_CR_PMM) != 0)
390 return E_PAR;
391 if((cfg->AutomaticStop & ~QUADSPI_CR_APMS) != 0)
392 return E_PAR;
393
394 if(hqspi->status != QSPI_STATUS_READY)
395 return E_OBJ;
396
397 /*
398 * ステータス、エラー初期化
399 */
400 hqspi->errorcode = QSPI_ERROR_NONE;
401 hqspi->status = QSPI_STATUS_BUSY_AP;
402
403 /*
404 * READY待ち
405 */
406 ercd = qspi_waitflag(hqspi, QUADSPI_SR_BUSY, 0, Timeout, &Timeout);
407 if(ercd != E_OK)
408 return ercd;
409
410 /*
411 * PSMARレジスタ MATCH値セット
412 */
413 sil_wrw_mem((uint32_t *)(hqspi->base+TOFF_QUADSPI_PSMAR), cfg->Match);
414
415 /*
416 * PSMKRレジスタ MASK値セット
417 */
418 sil_wrw_mem((uint32_t *)(hqspi->base+TOFF_QUADSPI_PSMKR), cfg->Mask);
419
420 /*
421 * PIRレジスタ インターバル値セット
422 */
423 sil_wrw_mem((uint32_t *)(hqspi->base+TOFF_QUADSPI_PIR), cfg->Interval);
424
425 /*
426 * CRレジスタ MATCHモード、オートマチックストップモードセット
427 */
428 sil_modw_mem((uint32_t *)(hqspi->base+TOFF_QUADSPI_CR), (QUADSPI_CR_PMM | QUADSPI_CR_APMS), (cfg->MatchMode | cfg->AutomaticStop));
429
430 /* Clear interrupt */
431 sil_wrw_mem((uint32_t *)(hqspi->base+TOFF_QUADSPI_FCR), (QUADSPI_FCR_CTEF | QUADSPI_FCR_CSMF));
432
433 /*
434 * ステータスバイトサイズをセット
435 */
436 cmd->NbData = cfg->StatusBytesSize;
437
438 /*
439 * 通信用レジスタを設定
440 */
441 qspi_config(hqspi, cmd, QSPI_FUNCTIONAL_MODE_AUTO_POLLING);
442
443 /*
444 * 割込み設定と割込み待ち
445 */
446 sil_orw_mem((uint32_t *)(hqspi->base+TOFF_QUADSPI_CR), (QUADSPI_CR_TEIE | QUADSPI_CR_SMIE));
447 return qspi_eventwait(hqspi, QSPI_STATUS_BUSY_AP, Timeout);
448}
449
450/*
451 * QSPIデータ送信
452 * parameter1 hqspi QSPIハンドラへのポインタ
453 * parameter2 pData 送信データ領域へのポインタ
454 * parameter3 timeout タイムアウト時間(ms)
455 * return 正常終了時、E_OK
456 */
457ER
458qspi_transmit(QSPI_Handle_t *hqspi, uint32_t *pData, uint32_t Timeout)
459{
460 if(pData == NULL)
461 return E_PAR;
462 if(hqspi->status != QSPI_STATUS_READY)
463 return E_OBJ;
464
465 /*
466 * ステータス、エラー初期化
467 */
468 hqspi->errorcode = QSPI_ERROR_NONE;
469 hqspi->status = QSPI_STATUS_BUSY_TX;
470
471 /*
472 * 通信データ設定
473 */
474 hqspi->XferCount = 0;
475 hqspi->XferSize = sil_rew_mem((uint32_t *)(hqspi->base+TOFF_QUADSPI_DLR)) + 1;
476 hqspi->pBuffPtr = pData;
477
478 /*
479 * CCRレジスタにインダイレクト書込み設定
480 */
481 sil_modw_mem((uint32_t *)(hqspi->base+TOFF_QUADSPI_CCR), QUADSPI_CCR_FMODE, QSPI_FUNCTIONAL_MODE_INDIRECT_WRITE);
482
483 /*
484 * 割込みクリアと割込み設定
485 */
486 sil_wrw_mem((uint32_t *)(hqspi->base+TOFF_QUADSPI_FCR), (QUADSPI_FCR_CTEF | QUADSPI_FCR_CTCF));
487 sil_orw_mem((uint32_t *)(hqspi->base+TOFF_QUADSPI_CR), (QUADSPI_CR_TEIE | QUADSPI_CR_FTIE | QUADSPI_CR_TCIE));
488
489 return qspi_eventwait(hqspi, QSPI_STATUS_BUSY_TX, Timeout);
490}
491
492/*
493 * QSPIデータ受信
494 * parameter1 hqspi QSPIハンドラへのポインタ
495 * parameter2 pData 受信データ領域へのポインタ
496 * parameter3 timeout タイムアウト時間(ms)
497 * return 正常終了時、E_OK
498 */
499ER
500qspi_receive(QSPI_Handle_t *hqspi, uint32_t *pData, uint32_t Timeout)
501{
502 uint32_t addr_reg = sil_rew_mem((uint32_t *)(hqspi->base+TOFF_QUADSPI_AR));
503
504 if(hqspi->status != QSPI_STATUS_READY)
505 return E_OBJ;
506 if(pData == NULL)
507 return E_PAR;
508
509 /*
510 * ステータス、エラー初期化
511 */
512 hqspi->errorcode = QSPI_ERROR_NONE;
513 hqspi->status = QSPI_STATUS_BUSY_RX;
514
515 /*
516 * 通信データ設定
517 */
518 hqspi->XferCount = 0;
519 hqspi->XferSize = sil_rew_mem((uint32_t *)(hqspi->base+TOFF_QUADSPI_DLR)) + 1;
520 hqspi->pBuffPtr = pData;
521
522 /*
523 * CCRレジスタにインダイレクト読込み設定
524 */
525 sil_modw_mem((uint32_t *)(hqspi->base+TOFF_QUADSPI_CCR), QUADSPI_CCR_FMODE, QSPI_FUNCTIONAL_MODE_INDIRECT_READ);
526
527 /*
528 * ARレジスタを再設定
529 */
530 sil_wrw_mem((uint32_t *)(hqspi->base+TOFF_QUADSPI_AR), addr_reg);
531
532 /*
533 * 割込みクリアと割込み設定
534 */
535 sil_wrw_mem((uint32_t *)(hqspi->base+TOFF_QUADSPI_FCR), (QUADSPI_FCR_CTEF | QUADSPI_FCR_CTCF));
536 sil_orw_mem((uint32_t *)(hqspi->base+TOFF_QUADSPI_CR), (QUADSPI_CR_TEIE | QUADSPI_CR_FTIE | QUADSPI_CR_TCIE));
537
538 return qspi_eventwait(hqspi, QSPI_STATUS_BUSY_RX, Timeout);
539}
540
541
542/*
543 * QSPIデバイスの初期化
544 * parameter1 hi2c I2Cハンドラへのポインタ
545 * return ハンドラへのポインタ
546 */
547QSPI_Handle_t *
548qspi_init(ID port, QSPI_Init_t *pini)
549{
550 GPIO_Init_t GPIO_Init_Data;
551 QSPI_Init_t *cfg;
552 const QSPI_PortControlBlock *qpcb;
553 QSPI_Handle_t *hqspi = NULL;
554 ER ercd = E_OK;
555 uint32_t no, temp;
556
557 if(port < QSPI1_PORTID || port > NUM_QSPIPORT)
558 return NULL;
559 if(pini == NULL)
560 return NULL;
561 if((pini->ddrmode & ~QUADSPI_CCR_DDRM) != 0)
562 return NULL;
563 if((pini->sioomode & ~QUADSPI_CCR_SIOO) != 0)
564 return NULL;
565
566 no = INDEX_QSPI(port);
567 hqspi = &QSPIHandle[no];
568 memset(hqspi, 0, sizeof(QSPI_Handle_t));
569 qpcb = &qspi_pcb[no];
570 hqspi->base = qpcb->base;
571
572 /*
573 * QSPIクロックイネーブル後リセット
574 */
575 sil_orw_mem((uint32_t *)(TADR_RCC_BASE+TOFF_RCC_AHB3ENR), RCC_AHB3ENR_QSPIEN);
576 temp = sil_rew_mem((uint32_t *)(TADR_RCC_BASE+TOFF_RCC_AHB3ENR));
577 sil_orw_mem((uint32_t *)(TADR_RCC_BASE+TOFF_RCC_AHB3RSTR), RCC_AHB3RSTR_QSPIRST);
578 sil_andw_mem((uint32_t *)(TADR_RCC_BASE+TOFF_RCC_AHB3RSTR), RCC_AHB3RSTR_QSPIRST);
579 (void)(temp);
580
581 /*
582 * GPIOの初期化
583 */
584 sil_orw_mem((uint32_t *)(qpcb->gioclockbase), qpcb->giocsclockbit);
585 sil_orw_mem((uint32_t *)(qpcb->gioclockbase), qpcb->gioclkclockbit);
586 sil_orw_mem((uint32_t *)(qpcb->gioclockbase), qpcb->giod0clockbit);
587 sil_orw_mem((uint32_t *)(qpcb->gioclockbase), qpcb->giod1clockbit);
588 sil_orw_mem((uint32_t *)(qpcb->gioclockbase), qpcb->giod2clockbit);
589 sil_orw_mem((uint32_t *)(qpcb->gioclockbase), qpcb->giod3clockbit);
590
591 GPIO_Init_Data.mode = GPIO_MODE_AF;
592 GPIO_Init_Data.pull = GPIO_PULLUP;
593 GPIO_Init_Data.otype = GPIO_OTYPE_PP;
594 GPIO_Init_Data.speed = GPIO_SPEED_HIGH;
595 GPIO_Init_Data.alternate = qpcb->giocsaf;
596 gpio_setup(qpcb->giocsbase, &GPIO_Init_Data, qpcb->giocspin);
597
598 GPIO_Init_Data.pull = GPIO_NOPULL;
599 GPIO_Init_Data.alternate = qpcb->gioclkaf;
600 gpio_setup(qpcb->gioclkbase, &GPIO_Init_Data, qpcb->gioclkpin);
601
602 GPIO_Init_Data.alternate = qpcb->giod0af;
603 gpio_setup(qpcb->giod0base, &GPIO_Init_Data, qpcb->giod0pin);
604
605 GPIO_Init_Data.alternate = qpcb->giod1af;
606 gpio_setup(qpcb->giod1base, &GPIO_Init_Data, qpcb->giod1pin);
607
608 GPIO_Init_Data.alternate = qpcb->giod2af;
609 gpio_setup(qpcb->giod2base, &GPIO_Init_Data, qpcb->giod2pin);
610
611 GPIO_Init_Data.alternate = qpcb->giod3af;
612 gpio_setup(qpcb->giod3base, &GPIO_Init_Data, qpcb->giod3pin);
613
614 hqspi->timeout = QPSI_TIMEOUT_DEFAULT_VALUE;
615 cfg = &hqspi->Init;
616 memcpy(cfg, pini, sizeof(QSPI_Init_t));
617
618 if((ercd = qspi_reinit(hqspi)) != E_OK)
619 return NULL;
620
621 /*
622 * 初期化終了関数の実行
623 */
624 if(pini->init_func != NULL){
625 ercd = pini->init_func(hqspi);
626 if(ercd != E_OK){
627 syslog_0(LOG_ERROR, "qspi_ini: config.init failed.");
628 return NULL;
629 }
630 }
631 return hqspi;
632}
633
634/*
635 * QSPIデバイスの無効化
636 * parameter1 hqspi QSPIハンドラへのポインタ
637 * return 正常終了時、E_OK
638 */
639ER
640qspi_deinit(QSPI_Handle_t *hqspi)
641{
642 /*
643 * QSPI無効化
644 */
645 sil_andw_mem((uint32_t *)(hqspi->base+TOFF_QUADSPI_CR), QUADSPI_CR_EN);
646 hqspi->errorcode = QSPI_ERROR_NONE;
647 hqspi->status = QSPI_STATUS_RESET;
648
649 /*
650 * QSPIリセット後クロック停止
651 */
652 sil_orw_mem((uint32_t *)(TADR_RCC_BASE+TOFF_RCC_AHB3RSTR), RCC_AHB3RSTR_QSPIRST);
653 sil_andw_mem((uint32_t *)(TADR_RCC_BASE+TOFF_RCC_AHB3RSTR), RCC_AHB3RSTR_QSPIRST);
654 sil_andw_mem((uint32_t *)(TADR_RCC_BASE+TOFF_RCC_AHB3ENR), RCC_AHB3ENR_QSPIEN);
655 return E_OK;
656}
657
658/*
659 * インダイレクト・フラッシュ・リード
660 * parameter1 hqspi QSPIハンドラへのポインタ
661 * parameter2 dst 読み込みアドレス
662 * parameter3 src フラッシュROMスタートアドレス
663 * parameter4 size 読み込みサイズ
664 * return 正常終了時、E_OK
665 */
666ER
667qspi_read(QSPI_Handle_t *hqspi, void * dst, uint32_t src, uint32_t size)
668{
669 QSPI_Init_t *cfg = &hqspi->Init;
670 QSPI_Command_t sCommand;
671 ER ercd = E_OK;
672
673 if(hqspi == NULL)
674 return E_PAR;
675 if(src >= cfg->device_size)
676 return E_PAR;
677 if((src + size - 1) >= cfg->device_size)
678 return E_PAR;
679 if(size == 0)
680 return E_PAR;
681 /*
682 * パラメータアラインチェック
683 */
684 if(((uintptr_t)dst & 0x3) || (src & 0x3) || (size & 0x3))
685 return E_PAR;
686
687 sCommand.InstructionMode = hqspi->Init.inst_type;
688 sCommand.Instruction = hqspi->Init.read_op_code;
689 sCommand.AddressMode = hqspi->Init.read_addr_xfer_type;
690 sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
691 sCommand.AddressSize = hqspi->Init.addr_size;
692 sCommand.AlternateBytesSize = 0;
693 sCommand.Address = src;
694 sCommand.DataMode = hqspi->Init.read_data_xfer_type;
695 sCommand.NbData = size;
696 sCommand.DummyCycles = hqspi->Init.read_dummy_cycles;
697
698
699 if((ercd = qspi_command(hqspi, &sCommand, hqspi->timeout)) != E_OK)
700 return ercd;
701
702#ifdef TOPPERS_STM32F769_DISCOVERY
703 sil_modw_mem((uint32_t *)(hqspi->base+TOFF_QUADSPI_DCR), QUADSPI_DCR_CSHT, QSPI_CS_HIGH_TIME_1_CYCLE);
704#endif
705
706 ercd = qspi_receive(hqspi, dst, hqspi->timeout);
707#ifdef TOPPERS_STM32F769_DISCOVERY
708 sil_modw_mem((uint32_t *)(hqspi->base+TOFF_QUADSPI_DCR), QUADSPI_DCR_CSHT, QSPI_CS_HIGH_TIME_4_CYCLE);
709#endif
710 return ercd;
711}
712
713/*
714 * インダイレクト・フラッシュ・ライト
715 * parameter1 hqspi QSPIハンドラへのポインタ
716 * parameter2 dst フラッシュROMスタートアドレス
717 * parameter3 src 書き込みデータアドレス
718 * parameter4 size 書き込みサイズ
719 * return 正常終了時、E_OK
720 */
721ER
722qspi_write(QSPI_Handle_t *hqspi, uint32_t dst, const void * src, uint32_t size)
723{
724 QSPI_Init_t *cfg = &hqspi->Init;
725 QSPI_Command_t sCommand;
726 uint32_t len, no = 0;
727 uint8_t *p = (uint8_t *)src;
728 ER ercd = E_OK;
729
730 if(hqspi == NULL)
731 return E_PAR;
732 if(dst >= cfg->device_size)
733 return E_PAR;
734 if((dst + size - 1) >= cfg->device_size)
735 return E_PAR;
736 if(size == 0)
737 return E_PAR;
738 /*
739 * パラメータアラインチェック
740 */
741 if(((uintptr_t)src & 0x3) || (dst & 0x3) || (size & 0x3))
742 return E_PAR;
743
744 while(no < size && ercd == E_OK){
745 len = MIN(size, QSPI_WRITE_SIZE);
746
747 /*
748 * 書込みイネーブル設定
749 */
750 if(hqspi->Init.enable_write_func != NULL)
751 ercd = hqspi->Init.enable_write_func(hqspi, hqspi->timeout);
752 if(ercd != E_OK)
753 return ercd;
754
755 /*
756 * 書込みコマンド設定
757 */
758 sCommand.InstructionMode = hqspi->Init.inst_type;
759 sCommand.Instruction = hqspi->Init.write_op_code;
760 sCommand.AddressMode = hqspi->Init.write_addr_xfer_type;
761 sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
762 sCommand.AddressSize = hqspi->Init.addr_size;
763 sCommand.AlternateBytesSize = 0;
764 sCommand.Address = dst + no;
765 sCommand.DataMode = hqspi->Init.write_data_xfer_type;
766 sCommand.NbData = len;
767 sCommand.DummyCycles = hqspi->Init.write_dummy_cycles;
768
769 if((ercd = qspi_command(hqspi, &sCommand, hqspi->timeout)) != E_OK)
770 return ercd;
771
772 if((ercd = qspi_transmit(hqspi, (uint32_t *)(p+no), hqspi->timeout)) != E_OK)
773 return ercd;
774 /*
775 * 書込み完了待ち
776 */
777 if(hqspi->Init.wait_func != NULL)
778 ercd = hqspi->Init.wait_func(hqspi, hqspi->timeout);
779 no += len;
780 }
781 return ercd;
782}
783
784/*
785 * セクター消去
786 * parameter1 hqspi QSPIハンドラへのポインタ
787 * parameter2 address セクター先頭アドレス
788 * return 正常終了時、E_OK
789 */
790ER
791qspi_erase_sector(QSPI_Handle_t *hqspi, uint32_t address)
792{
793 QSPI_Command_t sCommand;
794 ER ercd = E_OK;
795
796 /*
797 * 書込みイネーブル設定
798 */
799 if(hqspi->Init.enable_write_func != NULL)
800 ercd = hqspi->Init.enable_write_func(hqspi, hqspi->timeout);
801 if(ercd != E_OK)
802 return ercd;
803
804 /*
805 * ERASEコマンド設定
806 */
807 sCommand.InstructionMode = hqspi->Init.inst_type; /* F */
808 sCommand.Instruction = hqspi->Init.erase_cmds[0];
809 sCommand.AddressMode = hqspi->Init.erase_addr_xfer_type;
810 sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; /* F */
811 sCommand.AlternateBytesSize = 0; /* NU */
812 sCommand.AddressSize = hqspi->Init.addr_size; /* F */
813 sCommand.Address = address;
814 sCommand.DataMode = QSPI_DATA_NONE;
815 sCommand.NbData = 0;
816 sCommand.DummyCycles = 0;
817
818 if((ercd = qspi_command(hqspi, &sCommand, hqspi->timeout)) != E_OK)
819 return ercd;
820
821 if(hqspi->Init.wait_func != NULL)
822 ercd = hqspi->Init.wait_func(hqspi, hqspi->timeout);
823 return ercd;
824}
825
826/*
827 * フラッシュメモリの消去
828 * parameter1 hqspi QSPIハンドラへのポインタ
829 * parameter2 address 消去領域の先頭アドレス
830 * parameter3 size 消去バイトサイズ
831 * return 正常終了時、E_OK
832 */
833ER
834qspi_erase(QSPI_Handle_t *hqspi, uint32_t address, uint32_t size)
835{
836 QSPI_Init_t *cfg = &hqspi->Init;
837 uint32_t actual_address = address;
838 uint32_t actual_size = size;
839 uint32_t remainder;
840 ER ercd = E_OK;
841
842 /*
843 * パラメータチェック
844 */
845 if(hqspi == NULL)
846 return E_PAR;
847 if((address + size) > cfg->device_size)
848 return E_PAR;
849 if((address + size) > cfg->device_size)
850 return E_PAR;
851
852 /*
853 * 消去アライン補正
854 */
855 remainder = address % cfg->erase_sizes[0];
856 if(remainder != 0){
857 actual_address -= remainder;
858 actual_size += remainder;
859 }
860 remainder = actual_size % cfg->erase_sizes[0];
861 if(remainder != 0){
862 remainder = cfg->erase_sizes[0] - remainder;
863 actual_size += remainder;
864 }
865
866 /*
867 * 補正が必要ならパラメータエラー
868 */
869 if((actual_address != address) || (actual_size != size))
870 return E_PAR;
871
872 while(size > 0){
873 if((ercd = qspi_erase_sector(hqspi, address)) != E_OK)
874 break;
875 address += cfg->erase_sizes[0];
876 size -= cfg->erase_sizes[0];
877 }
878 return ercd;
879}
880
881/*
882 * ダイレクト・アクセス無効化
883 * parameter1 hqspi QSPIハンドラへのポインタ
884 * return 正常終了時、E_OK
885 */
886ER
887qspi_direct_disable(QSPI_Handle_t *hqspi)
888{
889 /*
890 * QSPI無効化
891 */
892 sil_andw_mem((uint32_t *)(hqspi->base+TOFF_QUADSPI_CR), QUADSPI_CR_EN);
893
894 /*
895 * QSPIリセット後クロック停止
896 */
897 sil_orw_mem((uint32_t *)(TADR_RCC_BASE+TOFF_RCC_AHB3RSTR), RCC_AHB3RSTR_QSPIRST);
898 sil_andw_mem((uint32_t *)(TADR_RCC_BASE+TOFF_RCC_AHB3RSTR), RCC_AHB3RSTR_QSPIRST);
899 return qspi_reinit(hqspi);
900}
901
902/*
903 * ダイレクト・アクセス有効化
904 * parameter1 hqspi QSPIハンドラへのポインタ
905 * return 正常終了時、E_OK
906 */
907ER
908qspi_direct_enable(QSPI_Handle_t *hqspi)
909{
910 QSPI_Command_t sCommand;
911 uint32_t Timeout = hqspi->timeout;
912 ER ercd = E_OK;
913
914 if(hqspi->status != QSPI_STATUS_READY)
915 return E_OBJ;
916
917 /*
918 * 読み出しコマンド設定
919 */
920 sCommand.InstructionMode = hqspi->Init.inst_type;
921 sCommand.Instruction = hqspi->Init.read_op_code;
922 sCommand.AddressMode = hqspi->Init.read_addr_xfer_type;
923 sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
924 sCommand.AlternateBytesSize = 0;
925 sCommand.AddressSize = hqspi->Init.addr_size;
926 sCommand.Address = 0;
927 sCommand.DataMode = hqspi->Init.read_data_xfer_type;
928 sCommand.NbData = 0;
929 sCommand.DummyCycles = hqspi->Init.read_dummy_cycles;
930
931 /*
932 * READY待ち
933 */
934 if((ercd = qspi_waitflag(hqspi, QUADSPI_SR_BUSY, 0, Timeout, &Timeout)) != E_OK)
935 return ercd;
936
937 hqspi->errorcode = QSPI_ERROR_NONE;
938 hqspi->status = QSPI_STATUS_BUSY_MM;
939
940 /*
941 * 通信レジスタ設定
942 */
943 qspi_config(hqspi, &sCommand, QSPI_FUNCTIONAL_MODE_MEMORY_MAPPED);
944 return E_OK;
945}
946
947/*
948 * QSPI割込みハンドラ
949 */
950void
951qspi_handler(QSPI_Handle_t *hqspi)
952{
953 uint32_t sr = sil_rew_mem((uint32_t *)(hqspi->base+TOFF_QUADSPI_SR));
954 uint32_t cr = sil_rew_mem((uint32_t *)(hqspi->base+TOFF_QUADSPI_CR));
955
956 hqspi->istatus = sr;
957 /*
958 * QSPI FIFOスレッシュ割込み
959 */
960 if((sr & QUADSPI_SR_FTF) != 0 && (cr & QUADSPI_CR_FTIE) != 0){
961 if(hqspi->status == QSPI_STATUS_BUSY_TX){
962 /* Transmission process */
963 while((sil_rew_mem((uint32_t *)(hqspi->base+TOFF_QUADSPI_SR)) & QUADSPI_SR_FTF) != 0){
964 if(hqspi->XferCount < hqspi->XferSize){
965 sil_wrw_mem((uint32_t *)(hqspi->base+TOFF_QUADSPI_DR), *hqspi->pBuffPtr++);
966 hqspi->XferCount += 4;
967 }
968 else{ /* FIFO割込みマスク */
969 sil_andw_mem((uint32_t *)(hqspi->base+TOFF_QUADSPI_CR), QUADSPI_CR_FTIE);
970 break;
971 }
972 }
973 }
974 else if(hqspi->status == QSPI_STATUS_BUSY_RX){
975 /* Receiving Process */
976 while((sil_rew_mem((uint32_t *)(hqspi->base+TOFF_QUADSPI_SR)) & QUADSPI_SR_FTF) != 0){
977 if(hqspi->XferCount < hqspi->XferSize){
978 *hqspi->pBuffPtr++ = (uint32_t)sil_rew_mem((uint32_t *)(hqspi->base+TOFF_QUADSPI_DR));
979 hqspi->XferCount += 4;
980 }
981 else{ /* FIFO割込みマスク */
982 sil_andw_mem((uint32_t *)(hqspi->base+TOFF_QUADSPI_CR), QUADSPI_CR_FTIE);
983 break;
984 }
985 }
986 }
987 }
988
989 /*
990 * QSPI転送終了割込み
991 */
992 else if((sr & QUADSPI_SR_TCF) != 0 && (cr & QUADSPI_CR_TCIE) != 0){
993 /*
994 * 割込みクリア、要因マスク
995 */
996 sil_wrw_mem((uint32_t *)(hqspi->base+TOFF_QUADSPI_FCR), QUADSPI_FCR_CTCF);
997 sil_andw_mem((uint32_t *)(hqspi->base+TOFF_QUADSPI_CR), (QUADSPI_CR_TCIE | QUADSPI_CR_TEIE | QUADSPI_CR_FTIE));
998
999 /* Transfer complete callback */
1000 if(hqspi->status == QSPI_STATUS_BUSY_TX){
1001 /* Change state of QSPI */
1002 hqspi->status = QSPI_STATUS_READY;
1003 if(hqspi->semid != 0)
1004 isig_sem(hqspi->semid);
1005 }
1006 else if(hqspi->status == QSPI_STATUS_BUSY_RX){
1007 while((sil_rew_mem((uint32_t *)(hqspi->base+TOFF_QUADSPI_SR)) & QUADSPI_SR_FLEVEL) != 0){
1008 if (hqspi->XferCount < hqspi->XferSize){
1009 *hqspi->pBuffPtr++ = (uint32_t)sil_rew_mem((uint32_t *)(hqspi->base+TOFF_QUADSPI_DR));
1010 hqspi->XferCount += 4;
1011 }
1012 else{
1013 /* All data have been received for the transfer */
1014 break;
1015 }
1016 }
1017 /* Change state of QSPI */
1018 hqspi->status = QSPI_STATUS_READY;
1019 if(hqspi->semid != 0)
1020 isig_sem(hqspi->semid);
1021 }
1022 else if(hqspi->status == QSPI_STATUS_BUSY){
1023 /*
1024 * コマンド送信終了
1025 */
1026 hqspi->status = QSPI_STATUS_READY;
1027 if(hqspi->semid != 0)
1028 isig_sem(hqspi->semid);
1029 }
1030 }
1031
1032 /*
1033 * QSPI Status Match割込み
1034 */
1035 else if((sr & QUADSPI_SR_SMF) != 0 && (cr & QUADSPI_CR_SMIE) != 0){
1036 /*
1037 * STATUS MATCH割込みクリア
1038 */
1039 sil_wrw_mem((uint32_t *)(hqspi->base+TOFF_QUADSPI_FCR), QUADSPI_FCR_CSMF);
1040 /*
1041 * AUTOMATIC POLL MODE終了
1042 */
1043 if((sil_rew_mem((uint32_t *)(hqspi->base+TOFF_QUADSPI_CR)) & QUADSPI_CR_APMS) != 0){
1044 /*
1045 * 割込みマスクとステータス変更
1046 */
1047 sil_andw_mem((uint32_t *)(hqspi->base+TOFF_QUADSPI_CR), (QUADSPI_CR_SMIE | QUADSPI_CR_TEIE));
1048 hqspi->status = QSPI_STATUS_READY;
1049 }
1050 if(hqspi->semid != 0)
1051 isig_sem(hqspi->semid);
1052 }
1053
1054 /*
1055 * QSPI Transfer Error割込み
1056 */
1057 else if((sr & QUADSPI_SR_TEF) != 0 && (cr & QUADSPI_CR_TEIE) != 0){
1058 /* Clear interrupt */
1059 sil_wrw_mem((uint32_t *)(hqspi->base+TOFF_QUADSPI_FCR), QUADSPI_FCR_CTEF);
1060
1061 /* Disable all the QSPI Interrupts */
1062 sil_andw_mem((uint32_t *)(hqspi->base+TOFF_QUADSPI_CR), (QUADSPI_CR_SMIE | QUADSPI_CR_TCIE | QUADSPI_CR_TEIE | QUADSPI_CR_FTIE));
1063
1064 /* Set error code */
1065 hqspi->errorcode |= QSPI_ERROR_TRANERR;
1066
1067 /* Change state of QSPI */
1068 hqspi->status = QSPI_STATUS_READY;
1069
1070 /*
1071 * エラーコールバック
1072 */
1073 if(hqspi->errorcallback != NULL)
1074 hqspi->errorcallback(hqspi);
1075 }
1076
1077 /*
1078 * QSPI Timeout割込み
1079 */
1080 else if((sr & QUADSPI_SR_TOF) != 0 && (cr & QUADSPI_CR_TOIE) != 0){
1081 /*
1082 * タイマー割込みクリア
1083 */
1084 sil_wrw_mem((uint32_t *)(hqspi->base+TOFF_QUADSPI_FCR), QUADSPI_FCR_CTOF);
1085
1086 /*
1087 * タイムアウトコールバック
1088 */
1089 if(hqspi->timeoutcallback != NULL)
1090 hqspi->timeoutcallback(hqspi);
1091 }
1092}
1093
1094
1095/*
1096 * QSPI割込みサービスルーチン
1097 */
1098void qspi_isr(intptr_t exinf)
1099{
1100 qspi_handler(&QSPIHandle[INDEX_QSPI((uint32_t)exinf)]);
1101}
1102
1103
Note: See TracBrowser for help on using the repository browser.