2 * Simulator of microcontrollers (flash.cc)
4 * Copyright (C) 2017 Drotos Daniel
6 * To contact author send email to dr.dkdb@gmail.com
10 /* This file is part of microcontroller simulator: ucsim.
12 UCSIM is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 2 of the License, or
15 (at your option) any later version.
17 UCSIM is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with UCSIM; see the file COPYING. If not, write to the Free
24 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
38 /* Address space/cell which can contain flash memory */
41 cl_flash_cell::write(t_mem val
)
43 if (flags
& CELL_READ_ONLY
)
45 class cl_stm8
*uc
= (cl_stm8
*)(application
->get_uc());
49 if (uc
->rom
->is_owned(this, &a
) &&
52 uc
->flash_ctrl
->flash_write(a
, val
);
57 return cl_cell8::write(val
);
60 cl_flash_as::cl_flash_as(const char *id
, t_addr astart
, t_addr asize
):
61 cl_address_space(id
, astart
, asize
, 8)
63 class cl_flash_cell
c8(8);
64 class cl_memory_cell
*cell
= &c8
;
65 start_address
= astart
;
66 decoders
= new cl_decoder_list(2, 2, false);
67 cella
= (class cl_memory_cell
*)malloc(size
* sizeof(class cl_memory_cell
));
68 int s1
= sizeof(class cl_memory_cell
);
69 int s2
= sizeof(class cl_flash_cell
);
70 printf("s1=%d s2=%d\n", s1
, s2
);
73 for (i
= 0; i
< size
; i
++)
76 memcpy(p
, (void*)cell
, sizeof(class cl_memory_cell
));
79 dummy
= new cl_dummy_cell(8);
84 cl_flash_as::init(void)
86 return cl_memory::init();
90 cl_iapsr_op::cl_iapsr_op(class cl_memory_cell
*acell
):
91 cl_memory_operator(acell
)
93 set_name("EOP_clearer");
96 // read clears EOP and WR_PG_DIS bits
98 cl_iapsr_op::read(void)
100 t_mem v
= cell
->get();
106 /* Flash controller */
108 cl_flash::cl_flash(class cl_uc
*auc
, t_addr abase
, const char *aname
):
109 cl_hw(auc
, HW_FLASH
, 0, aname
)
127 cl_flash::reset(void)
129 uc
->sim
->app
->debug("FLASH reset\n");
140 cr1r
->set
/*write*/(0);
141 iapsr
->set
/*write*/(0x40);
142 cr2r
->set
/*write*/(0);
144 ncr2r
->set
/*write*/(0xff);
149 cl_flash::cfg_help(t_addr addr
)
153 case stm8_flash_on
: return "Turn ticking of flash on/off (bool, RW)";
160 cl_flash::tick(int cycles
)
164 double now
= uc
->ticks
->get_rtime();
165 double elapsed
= (now
- start_time
) * 10e6
;
167 if ((state
== fs_pre_erase
) &&
168 (elapsed
> tprog
/2.0))
171 uc
->sim
->app
->debug("FLASH zeroing %06lx .. %d\n", wbuf_start
, wbuf_size
);
172 for (i
= 0; i
< wbuf_size
; i
++)
174 class cl_memory_cell
*c
= uc
->rom
->get_cell(wbuf_start
+ i
);
177 if (mode
== fm_erase
)
179 uc
->sim
->app
->debug("FLASH end of erase, finish\n");
180 finish_program(true);
184 uc
->sim
->app
->debug("FLASH end of erase, cont program\n");
188 else if (elapsed
> tprog
)
191 uc
->sim
->app
->debug("FLASH dl-ing %06lx .. %06l\n", wbuf_start
, wbuf_start
+wbuf_size
);
192 for (i
= 0; i
< wbuf_size
; i
++)
194 class cl_memory_cell
*c
= uc
->rom
->get_cell(wbuf_start
+ i
);
195 t_mem org
= c
->get(), n
;
198 uc
->sim
->app
->debug("FLASH dl [%06lx]= %x (org=%x)\n",
199 wbuf_start
+i
, n
, org
);
201 uc
->sim
->app
->debug("FLASH end of program\n");
202 finish_program(true);
209 cl_flash::finish_program(bool ok
)
212 iapsr
->set(iapsr
->get() | 0x04);
214 iapsr
->set(iapsr
->get() | 0x01);
215 uc
->sim
->app
->debug("FLASH prg finish, OK=%d iapsr=%02x\n", ok
, iapsr
->get());
220 cl_flash::read(class cl_memory_cell
*cell
)
224 if (conf(cell
, NULL
))
230 else if (cell
== dukr
)
232 else if (cell
== iapsr
)
241 uc
->sim
->app
->debug("FLASH read iapsr5 %02x\n",v
);
244 // clear of EOP and WR_PG_DIS bits will be done by cl_iapsr_op
251 cl_flash::write(class cl_memory_cell
*cell
, t_mem
*val
)
258 uc
->sim
->app
->debug("FLASH write-pukr %02x\n",*val
);
271 puk1st
= false, p_unlocked
= true;
273 puk1st
= false, p_failed
= true;
277 else if (cell
== dukr
)
279 uc
->sim
->app
->debug("FLASH write-dukr %02x\n",*val
);
292 duk1st
= false, d_unlocked
= true;
294 duk1st
= false, d_failed
= true;
298 else if (cell
== iapsr
)
300 uc
->sim
->app
->debug("FLASH write-iapsr %02x\n",*val
);
301 t_mem org
= iapsr
->get();
304 p_unlocked
= puk1st
= false;
306 d_unlocked
= duk1st
= false;
319 else if (cell
== cr2r
)
321 uc
->sim
->app
->debug("FLASH write-cr2r %02x\n",*val
);
326 *val
|= (cr2r
->get() & 0x30);
328 if ((ncr2r
== NULL
) ||
329 (ncr2r
->get() == ((~(*val
))&0xff)))
330 set_flash_mode(*val
);
332 else if ((ncr2r
!= NULL
) &&
335 uc
->sim
->app
->debug("FLASH write-ncr2r %02x\n",*val
);
340 *val
|= (ncr2r
->get() & 0x30);
342 if (cr2r
->get() == ((~(*val
))&0xff))
343 set_flash_mode((~(*val
))&0xff);
349 cl_flash::conf_op(cl_memory_cell
*cell
, t_addr addr
, t_mem
*val
)
351 switch ((enum stm8_flash_cfg
)addr
)
364 case stm8_flash_nuof_cfg
:
372 cl_flash::flash_write(t_addr a
, t_mem val
)
374 uc
->sim
->app
->debug("FLASH wr(%06lx,%02x)\n",a
,val
);
377 uc
->sim
->app
->debug(" no uc\n");
382 uc
->sim
->app
->debug(" no rom\n");
388 uc
->sim
->app
->debug(" plocked\n");
394 uc
->sim
->app
->debug(" dlocked\n");
399 uc
->sim
->app
->debug(" busy %d\n",state
);
403 uc
->sim
->app
->debug(" wbuf_start=%06lx\n",wbuf_start
);
406 uc
->sim
->app
->debug(" calling start_wbuf(%06lx)\n",a
);
410 int offset
= a
- wbuf_start
;
411 uc
->sim
->app
->debug(" offset=%d\n",offset
);
415 wbuf
[0]= uc
->rom
->get(wbuf_start
+ 0);
416 wbuf
[1]= uc
->rom
->get(wbuf_start
+ 1);
417 wbuf
[2]= uc
->rom
->get(wbuf_start
+ 2);
418 wbuf
[3]= uc
->rom
->get(wbuf_start
+ 3);
429 start_program(fs_program
);
431 else if (mode
== fm_erase
)
433 uc
->sim
->app
->debug(" romwrite in erase mode\n");
436 if ((wbuf_writes
== 4) &&
446 uc
->sim
->app
->debug(" starting erase\n");
447 start_program(fs_pre_erase
);
456 if ((wbuf_writes
== wbuf_size
) ||
457 (offset
== wbuf_size
-1))
459 if ((mode
== fm_fast_word
) ||
460 (mode
== fm_fast_block
))
461 start_program(fs_program
);
463 start_program(fs_pre_erase
);
468 // normal program: 6 ms
469 // fast program: 3 ms
473 cl_flash::set_flash_mode(t_mem cr2val
)
475 bool fix
= cr1r
->get() & 0x01; /* FIX */
477 uc
->sim
->app
->debug("FLASH set_mode %02x\n", cr2val
);
478 if (cr2val
& 0x40 /* WPRG */ )
481 tprog
= 6000; /* normal mode */
484 else if (cr2val
& 0x20 /* ERASE */ )
490 else if (cr2val
& 0x10 /* FPRG */ )
496 else if (cr2val
& 0x01 /* PRG */ )
505 tprog
= fix
?6000:3000;
509 uc
->sim
->app
->debug("FLASH state=wait_data\n");
515 cl_flash::start_wbuf(t_addr addr
)
518 wbuf_start
= addr
- (addr
% wbuf_size
);
520 for (i
= 0; i
< 256; i
++)
522 uc
->sim
->app
->debug("FLASH start_wbuf %06lx (wbuf_start=%06lx,size=%d)\n", addr
, wbuf_start
, wbuf_size
);
526 cl_flash::start_program(enum stm8_flash_state start_state
)
528 uc
->sim
->app
->debug("FLASH start prg state=0x%x wbuf=%02x,%02x,%02x,%02x\n",
530 wbuf
[0], wbuf
[1], wbuf
[2], wbuf
[3]);
532 start_time
= uc
->ticks
->get_rtime();
536 cl_flash::state_name(enum stm8_flash_state s
)
540 case fs_wait_mode
: return "wait_mode";
541 case fs_wait_data
: return "wait_data";
542 case fs_pre_erase
: return "erase";
543 case fs_program
: return "program";
544 case fs_busy
: return "busy";
550 cl_flash::print_info(class cl_console_base
*con
)
552 con
->dd_printf(chars("", "Flash at %s\n", uc
->rom
->addr_format
), base
);
553 con
->dd_printf("PUK: ");
555 con
->dd_printf("fail");
557 con
->dd_printf("unlocked");
559 con
->dd_printf("MASS1");
561 con
->dd_printf("locked");
562 con
->dd_printf("\n");
564 con
->dd_printf("DUK: ");
566 con
->dd_printf("fail");
568 con
->dd_printf("unlocked");
570 con
->dd_printf("MASS1");
572 con
->dd_printf("locked");
573 con
->dd_printf("\n");
575 con
->dd_printf("State: %s\n", state_name(state
));
576 //print_cfg_info(con);
582 cl_saf_flash::cl_saf_flash(class cl_uc
*auc
, t_addr abase
):
583 cl_flash(auc
, abase
, "flash")
588 cl_saf_flash::registration(void)
592 cr1r
= register_cell(uc
->rom
, base
+0);
593 cr2r
= register_cell(uc
->rom
, base
+1);
594 ncr2r
= register_cell(uc
->rom
, base
+2);
595 iapsr
= register_cell(uc
->rom
, base
+5);
596 pukr
= register_cell(uc
->rom
, base
+8);
597 dukr
= register_cell(uc
->rom
, base
+10);
599 uc
->it_sources
->add(is
= new cl_it_src(uc
, 24,
602 0x8008+24*4, false, false,
603 "FLASH_EOP", 20*20+0));
604 uc
->it_sources
->add(is
= new cl_it_src(uc
, 24,
607 0x8008+24*4, false, false,
608 "FLASH_RO", 20*20+1));
611 class cl_iapsr_op
*o
= new cl_iapsr_op(iapsr
);
612 iapsr
->append_operator(o
);
618 cl_l_flash::cl_l_flash(class cl_uc
*auc
, t_addr abase
):
619 cl_flash(auc
, abase
, "flash")
624 cl_l_flash::registration(void)
628 cr1r
= register_cell(uc
->rom
, base
+0);
629 cr2r
= register_cell(uc
->rom
, base
+1);
630 pukr
= register_cell(uc
->rom
, base
+2);
631 dukr
= register_cell(uc
->rom
, base
+3);
632 iapsr
= register_cell(uc
->rom
, base
+4);
635 uc
->it_sources
->add(is
= new cl_it_src(uc
, 1,
638 0x8008+1*4, false, false,
639 "FLASH_EOP", 20*20+0));
640 uc
->it_sources
->add(is
= new cl_it_src(uc
, 1,
643 0x8008+1*4, false, false,
644 "FLASH_RO", 20*20+1));
649 /* End of stm8.src/flash.cc */