source: uKadecot/trunk/src/ukadecot/data_flash.c@ 108

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

MIMEプロパティの変更

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
  • Property svn:mime-type set to text/x-chdr; charset=SHIFT_JIS
File size: 11.3 KB
Line 
1/*
2 * TOPPERS ECHONET Lite Communication Middleware
3 *
4 * Copyright (C) 2014 Cores Co., Ltd. Japan
5 *
6 * 上記著作権者は,以下の(1)〜(4)の条件を満たす場合に限り,本ソフトウェ
7 * ア(本ソフトウェアを改変したものを含む.以下同じ)を使用・複製・改
8 * 変・再配布(以下,利用と呼ぶ)することを無償で許諾する.
9 * (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
10 * 権表示,この利用条件および下記の無保証規定が,そのままの形でソー
11 * スコード中に含まれていること.
12 * (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
13 * 用できる形で再配布する場合には,再配布に伴うドキュメント(利用
14 * 者マニュアルなど)に,上記の著作権表示,この利用条件および下記
15 * の無保証規定を掲載すること.
16 * (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
17 * 用できない形で再配布する場合には,次のいずれかの条件を満たすこ
18 * と.
19 * (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著
20 * 作権表示,この利用条件および下記の無保証規定を掲載すること.
21 * (b) 再配布の形態を,別に定める方法によって,TOPPERSプロジェクトに
22 * 報告すること.
23 * (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
24 * 害からも,上記著作権者およびTOPPERSプロジェクトを免責すること.
25 * また,本ソフトウェアのユーザまたはエンドユーザからのいかなる理
26 * 由に基づく請求からも,上記著作権者およびTOPPERSプロジェクトを
27 * 免責すること.
28 *
29 * 本ソフトウェアは,無保証で提供されているものである.上記著作権者お
30 * よびTOPPERSプロジェクトは,本ソフトウェアに関して,特定の使用目的
31 * に対する適合性も含めて,いかなる保証も行わない.また,本ソフトウェ
32 * アの利用により直接的または間接的に生じたいかなる損害に関しても,そ
33 * の責任を負わない.
34 *
35 * @(#) $Id: data_flash.c 108 2015-06-11 09:15:46Z coas-nagasima $
36 */
37
38/*
39 * サンプルプログラム(1)の本体
40 */
41
42#include <kernel.h>
43#include <t_syslog.h>
44#include <sil.h>
45#include "data_flash.h"
46#ifdef __RX
47#include "rx630_ccrx/rx630.h"
48#else
49#include "rx630_msvc/rx630.h"
50#endif
51#include "grsakura.h"
52
53#define FLASH_FWEPROR_ADDR ( ( volatile uint8_t __evenaccess * )0x0008C296 )
54
55#define FLASH_FMODR_ADDR ( ( volatile uint8_t __evenaccess * )0x007FC402 )
56#define FLASH_FMODR_FRDMD_BIT ( 0x01U << 4U )
57
58#define FLASH_DFLRE0_ADDR ( ( volatile uint16_t __evenaccess * )0x007FC440 )
59#define FLASH_DFLRE1_ADDR ( ( volatile uint16_t __evenaccess * )0x007FC442 )
60#define FLASH_DFLWE0_ADDR ( ( volatile uint16_t __evenaccess * )0x007FC450 )
61#define FLASH_DFLWE1_ADDR ( ( volatile uint16_t __evenaccess * )0x007FC452 )
62#define FLASH_FCURAME_ADDR ( ( volatile uint16_t __evenaccess * )0x007FC454 )
63
64#define FLASH_FASTAT_ADDR ( ( volatile uint8_t __evenaccess * )0x007FC410 )
65#define FLASH_FASTAT_DFLWPE_BIT ( 0x01U << 0 )
66#define FLASH_FASTAT_DFLRPE_BIT ( 0x01U << 1 )
67#define FLASH_FASTAT_DFLAE_BIT ( 0x01U << 3 )
68#define FLASH_FASTAT_CMDLK_BIT ( 0x01U << 4 )
69#define FLASH_FASTAT_ROMAE_BIT ( 0x01U << 7 )
70
71#define FLASH_FENTRYR_ADDR ( ( volatile uint16_t __evenaccess * )0x007FFFB2 )
72#define FLASH_FENTRYR_FENRTY0_BIT ( 0x0001U << 0U )
73#define FLASH_FENTRYR_FENRTY1_BIT ( 0x0001U << 1U )
74#define FLASH_FENTRYR_FENRTY2_BIT ( 0x0001U << 2U )
75#define FLASH_FENTRYR_FENRTY3_BIT ( 0x0001U << 3U )
76#define FLASH_FENTRYR_FENTRYD_BIT ( 0x0001U << 7U )
77
78#define FLASH_FRESETR_ADDR ( ( volatile uint16_t __evenaccess * )0x007FFFB6 )
79#define FLASH_FRESETR_FRESET_BIT ( 0x0001U << 0 )
80
81#define FLASH_DFLBCCNT_ADDR ( ( volatile uint16_t __evenaccess * )0x007FFFCA )
82#define FLASH_DFLBCCNT_BCSIZE_BIT ( 0x0001U << 15U )
83#define FLASH_DFLBCCNT_BCADR_OFFSET ( 0U )
84#define FLASH_DFLBCCNT_BCADR_MASK ( 0x7FFU << FLASH_DFLBCCNT_BCADR_OFFSET )
85
86#define FLASH_DFLBCSTAT_ADDR ( ( volatile uint16_t __evenaccess * )0x007FFFCE )
87#define FLASH_DFLBCSTAT_BCST_BIT ( 0x0001U << 0U )
88
89#define FLASH_FSTATR0_ADDR ( ( volatile uint8_t __evenaccess * )0x007FFFB0 )
90#define FLASH_FSTATR0_PRGSPD_BIT ( 0x01U << 0 )
91#define FLASH_FSTATR0_ERSSPD_BIT ( 0x01U << 1 )
92#define FLASH_FSTATR0_SUSRDY_BIT ( 0x01U << 3 )
93#define FLASH_FSTATR0_PRGERR_BIT ( 0x01U << 4 )
94#define FLASH_FSTATR0_ERSERR_BIT ( 0x01U << 5 )
95#define FLASH_FSTATR0_ILGLERR_BIT ( 0x01U << 6 )
96#define FLASH_FSTATR0_FRDY_BIT ( 0x01U << 7 )
97
98#define FLASH_PCKAR_ADDR ( ( volatile uint16_t __evenaccess * )0x007FFFE8 )
99
100#define DATA_FLASH_BLOCK_SIZE 32
101#ifndef _MSC_VER
102#define DATA_FLASH_BASE_ADDR 0x00100000
103#define FCU_FIRMWARE_ADDR 0xFEFFE000
104#define FCU_RAM_ADDR 0x007F8000
105#else
106uint8_t DATA_FLASH_BASE_ADDR[DATA_FLASH_BLOCK_SIZE * 1024];
107uint8_t FCU_FIRMWARE_ADDR[0x2000];
108uint8_t FCU_RAM_ADDR[0x2000];
109#endif
110
111static void fcu_init();
112static void fcu_copy_firm();
113static bool_t fcu_notify_clock();
114static void fcu_read_mode();
115static void fcu_pe_mode();
116static bool_t fcu_write(int blockno, void *data);
117static bool_t fcu_erase(int blockno);
118static bool_t fcu_check_blank(int blockno);
119static bool_t fcu_check_valid(int blockno);
120static bool_t fcu_check_frdy(int tWAIT);
121static bool_t fcu_check_error();
122
123ER data_flash_init()
124{
125 ER ret;
126
127 /* E2データフラッシュの読み込み許可 */
128 sil_wrh_mem(FLASH_DFLRE0_ADDR, 0x2DFF);
129 sil_wrh_mem(FLASH_DFLRE1_ADDR, 0xD2FF);
130 /* E2データフラッシュの書き込み許可 */
131 sil_wrh_mem(FLASH_DFLWE0_ADDR, 0x1EFF);
132 sil_wrh_mem(FLASH_DFLWE1_ADDR, 0xE1FF);
133
134 /* tE16K = 240ms*/
135 fcu_check_frdy(240000);
136
137 /* エラー確認 */
138 fcu_check_error();
139
140 /* FCUファームウェアのコピー */
141 fcu_copy_firm();
142
143 /* P/Eモード移行 */
144 fcu_pe_mode();
145
146 /* P/E ノーマルモード移行 */
147 *((uint8_t *)DATA_FLASH_BASE_ADDR) = 0xFF;
148
149 /* エラー確認 */
150 fcu_check_error();
151
152 /* 周辺クロック通知コマンド発行 */
153 ret = fcu_notify_clock();
154
155 /* リードモード移行 */
156 fcu_read_mode();
157
158 return ret ? E_OK : E_SYS;
159}
160
161ER data_flash_read(int blockno, void *data)
162{
163 uint16_t *wa, *end;
164 uint16_t *dst = (uint16_t *)data;
165
166 /* P/Eモード移行 */
167 fcu_pe_mode();
168
169 /* 有効データチェック */
170 if(!fcu_check_valid(blockno)){
171 /* リードモード移行 */
172 fcu_read_mode();
173 return E_OBJ;
174 }
175
176 /* リードモード移行 */
177 fcu_read_mode();
178
179 wa = (uint16_t *)(DATA_FLASH_BLOCK_SIZE * blockno + (intptr_t)DATA_FLASH_BASE_ADDR);
180 end = &wa[DATA_FLASH_BLOCK_SIZE/sizeof(uint16_t)];
181
182 /* 読み出し */
183 for(; wa < end; wa++, dst++){
184 *dst = *wa;
185 }
186
187 return E_OK;
188}
189
190ER data_flash_write(int blockno, void *data)
191{
192 bool_t ret = true;
193
194 /* P/Eモード移行 */
195 fcu_pe_mode();
196
197 /* ブランクチェック */
198 if(!fcu_check_blank(blockno)){
199 /* ブランクでないならブロック消去 */
200 ret = fcu_erase(blockno);
201 if(!ret)
202 syslog(LOG_DEBUG, "fcu_erase() result = %d", ret);
203 }
204
205 if(ret){
206 /* 書き込み */
207 ret = fcu_write(blockno, data);
208 if(!ret)
209 syslog(LOG_DEBUG, "fcu_write() result = %d", ret);
210 }
211
212 /* リードモード移行 */
213 fcu_read_mode();
214
215 return ret ? E_OK : E_SYS;
216}
217
218static void fcu_copy_firm()
219{
220 unsigned int *src, *dst, *end;
221
222 /* リードモード移行 */
223 if(sil_reh_mem(FLASH_FENTRYR_ADDR) != 0)
224 sil_wrh_mem(FLASH_FENTRYR_ADDR, 0xAA00);
225
226 /* FCU RAMアクセス許可 */
227 sil_wrh_mem(FLASH_FCURAME_ADDR, 0xC401);
228
229 /* FCUファームウェアをFCU RAMにコピー */
230 src = (unsigned int *)FCU_FIRMWARE_ADDR;
231 dst = (unsigned int *)FCU_RAM_ADDR;
232 end = &dst[0x2000 / sizeof(unsigned int)];
233 for(; dst < end; dst++, src++)
234 *dst = *src;
235}
236
237static bool_t fcu_notify_clock()
238{
239 volatile uint8_t *ra;
240 volatile uint16_t *wa;
241
242 ra = (volatile uint8_t *)(DATA_FLASH_BASE_ADDR);
243 wa = (volatile uint16_t *)ra;
244
245 /* 周波数を設定 */
246 sil_wrh_mem(FLASH_PCKAR_ADDR, 48/*FREQ_PCLK / 1000*/);
247
248 /* 周辺クロック通知コマンド発行 */
249 *ra = 0xE9;
250 *ra = 0x03;
251 *wa = 0x0F0F;
252 *wa = 0x0F0F;
253 *wa = 0x0F0F;
254 *ra = 0xD0;
255
256 /* 120μs */
257 fcu_check_frdy(120);
258
259 /* エラー確認 */
260 return !fcu_check_error();
261}
262
263/*
264 * リードモード移行
265 */
266static void fcu_read_mode()
267{
268 int i;
269
270 for(;;){
271 for(i = 0; i < 1000; i++){
272 sil_wrh_mem(FLASH_FENTRYR_ADDR, 0xAA00);
273
274 if(sil_reh_mem(FLASH_FENTRYR_ADDR) != 0)
275 continue;
276
277 sil_wrb_mem(FLASH_FWEPROR_ADDR, 0x02);
278 return;
279 }
280
281 syslog(LOG_WARNING, "fcu_read_mode");
282 }
283}
284
285/*
286 * P/Eモード移行
287 */
288static void fcu_pe_mode()
289{
290 sil_wrh_mem(FLASH_FENTRYR_ADDR, 0xAA80);
291 sil_wrb_mem(FLASH_FWEPROR_ADDR, 0x01);
292}
293
294static bool_t fcu_write(int blockno, void *data)
295{
296 volatile uint8_t *ra;
297 volatile uint16_t *wa, *end;
298 uint16_t *src = (uint16_t *)data;
299
300 ra = (volatile uint8_t *)(DATA_FLASH_BLOCK_SIZE * blockno + (intptr_t)DATA_FLASH_BASE_ADDR);
301 end = (volatile uint16_t *)(((intptr_t)ra) + DATA_FLASH_BLOCK_SIZE);
302
303 for(wa = (volatile uint16_t *)ra; wa < end; wa++, src++)
304 {
305 /* プログラムコマンド発行 */
306 *ra = 0xE8;
307 *ra = 0x01;
308 *wa = *src;
309 *ra = 0xD0;
310
311 /* 2ms×1.1 */
312 fcu_check_frdy(2200);
313
314 /* エラー確認 */
315 if(fcu_check_error())
316 return false;
317 }
318
319 return true;
320}
321
322static bool_t fcu_erase(int blockno)
323{
324 volatile uint8_t *ra;
325
326 ra = (volatile uint8_t *)(DATA_FLASH_BLOCK_SIZE * blockno + (intptr_t)DATA_FLASH_BASE_ADDR);
327
328 /* イレースコマンド発行 */
329 *ra = 0x20;
330 *ra = 0xD0;
331
332 /* 20ms×1.1 */
333 fcu_check_frdy(22000);
334
335 /* エラー確認 */
336 return !fcu_check_error();
337}
338
339static bool_t fcu_check_blank(int blockno)
340{
341 volatile uint8_t *ra;
342 volatile uint16_t *wa, *end;
343
344 sil_wrb_mem(FLASH_FMODR_ADDR, sil_reb_mem(FLASH_FMODR_ADDR) | FLASH_FMODR_FRDMD_BIT);
345
346 wa = (volatile uint16_t *)(DATA_FLASH_BLOCK_SIZE * blockno + (intptr_t)DATA_FLASH_BASE_ADDR);
347 end = (volatile uint16_t *)(((intptr_t)wa) + DATA_FLASH_BLOCK_SIZE);
348
349 for(; wa < end; wa++)
350 {
351 sil_wrh_mem(FLASH_DFLBCCNT_ADDR, (((intptr_t)wa) & FLASH_DFLBCCNT_BCADR_MASK) << FLASH_DFLBCCNT_BCADR_OFFSET);
352
353 ra = (volatile uint8_t *)wa;
354 *ra = 0x71;
355 *ra = 0xD0;
356
357 /* 30μs×1.1 */
358 fcu_check_frdy(33);
359
360 /* エラー確認 */
361 if(fcu_check_error())
362 return false;
363
364 /* ブランク確認 */
365 if((sil_reh_mem(FLASH_DFLBCSTAT_ADDR) & FLASH_DFLBCSTAT_BCST_BIT) != 0)
366 return false;
367 }
368
369 return true;
370}
371
372static bool_t fcu_check_valid(int blockno)
373{
374 volatile uint8_t *ra;
375 volatile uint16_t *wa, *end;
376
377 sil_wrb_mem(FLASH_FMODR_ADDR, sil_reb_mem(FLASH_FMODR_ADDR) | FLASH_FMODR_FRDMD_BIT);
378
379 wa = (volatile uint16_t *)(DATA_FLASH_BLOCK_SIZE * blockno + (intptr_t)DATA_FLASH_BASE_ADDR);
380 end = (volatile uint16_t *)(((intptr_t)wa) + DATA_FLASH_BLOCK_SIZE);
381
382 for(; wa < end; wa++)
383 {
384 sil_wrh_mem(FLASH_DFLBCCNT_ADDR, (((intptr_t)wa) & FLASH_DFLBCCNT_BCADR_MASK) << FLASH_DFLBCCNT_BCADR_OFFSET);
385
386 ra = (volatile uint8_t *)wa;
387 *ra = 0x71;
388 *ra = 0xD0;
389
390 /* 30μs×1.1 */
391 fcu_check_frdy(33);
392
393 /* エラー確認 */
394 if(fcu_check_error())
395 return false;
396
397 /* ブランク確認 */
398 if((sil_reh_mem(FLASH_DFLBCSTAT_ADDR) & FLASH_DFLBCSTAT_BCST_BIT) == 0)
399 return false;
400 }
401
402 return true;
403}
404
405static bool_t fcu_check_error()
406{
407 uint8_t status;
408
409 status = sil_reb_mem(FLASH_FSTATR0_ADDR);
410
411 if((status & (FLASH_FSTATR0_ILGLERR_BIT | FLASH_FSTATR0_ERSERR_BIT | FLASH_FSTATR0_PRGERR_BIT)) == 0)
412 return false;
413
414 if((status & FLASH_FSTATR0_ILGLERR_BIT) != 0){
415 if(sil_reb_mem(FLASH_FASTAT_ADDR) != 0x10){
416 sil_wrb_mem(FLASH_FASTAT_ADDR, 0x10);
417 }
418
419 /* ステータスクリアコマンド発行 */
420 *((uint8_t *)DATA_FLASH_BASE_ADDR) = 0x50;
421 }
422
423 syslog(LOG_WARNING, "fcu_check_error %02x", status);
424
425 return true;
426}
427
428static bool_t fcu_check_frdy(int tWAIT)
429{
430 int i, j;
431
432 for(i = 0; i < tWAIT; i++){
433 /* 準備完了なら終了 */
434 if((sil_reb_mem(FLASH_FSTATR0_ADDR) & FLASH_FSTATR0_FRDY_BIT) != 0)
435 return true;
436
437 /* 1μs? */
438 for(j = 0; j < 100; j++);
439 }
440
441 syslog(LOG_WARNING, "fcu_check_frdy timeout");
442
443 /* FCU初期化 */
444 fcu_init();
445
446 return false;
447}
448
449static void fcu_init()
450{
451 int j;
452
453 sil_wrh_mem(FLASH_FRESETR_ADDR, 0xCC01);
454
455 // 200μs? */
456 for(j = 0; j < 20000; j++);
457
458 sil_wrh_mem(FLASH_FRESETR_ADDR, 0xCC00);
459}
Note: See TracBrowser for help on using the repository browser.