[ucsim] Update email and file info, fix stm8 flash controller
[sdcc.git] / sdcc / sim / ucsim / src / sims / stm8.src / flash.cc
blobd9d1e4babb5bddab4b15b6615b79ed6275a76735
1 /*
2 * Simulator of microcontrollers (flash.cc)
4 * Copyright (C) 2017 Drotos Daniel
5 *
6 * To contact author send email to dr.dkdb@gmail.com
8 */
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
25 02111-1307, USA. */
26 /*@1@*/
28 #include <stdlib.h>
29 #include <string.h>
31 #include "globals.h"
33 #include "stm8cl.h"
35 #include "flashcl.h"
38 /* Address space/cell which can contain flash memory */
40 t_mem
41 cl_flash_cell::write(t_mem val)
43 if (flags & CELL_READ_ONLY)
45 class cl_stm8 *uc= (cl_stm8 *)(application->get_uc());
46 if (uc)
48 t_addr a;
49 if (uc->rom->is_owned(this, &a) &&
50 uc->flash_ctrl)
52 uc->flash_ctrl->flash_write(a, val);
53 return d();
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);
71 //cell->init();
72 t_addr i;
73 for (i= 0; i < size; i++)
75 void *p= &(cella[i]);
76 memcpy(p, (void*)cell, sizeof(class cl_memory_cell));
77 cella[i].init();
79 dummy= new cl_dummy_cell(8);
80 dummy->init();
83 int
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
97 t_mem
98 cl_iapsr_op::read(void)
100 t_mem v= cell->get();
101 cell->set(v&0x05);
102 return v;
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)
111 base= abase;
112 set_name(aname);
113 wbuf_started= false;
114 wbuf_start= 0;
115 rww= true;
119 cl_flash::init(void)
121 cl_hw::init();
122 registration();
123 return 0;
126 void
127 cl_flash::reset(void)
129 uc->sim->app->debug("FLASH reset\n");
130 puk1st= false;
131 duk1st= false;
132 p_unlocked= false;
133 d_unlocked= false;
134 p_failed= false;
135 d_failed= false;
137 state= fs_wait_mode;
138 mode= fm_unknown;
140 cr1r->set/*write*/(0);
141 iapsr->set/*write*/(0x40);
142 cr2r->set/*write*/(0);
143 if (ncr2r)
144 ncr2r->set/*write*/(0xff);
148 const char *
149 cl_flash::cfg_help(t_addr addr)
151 switch (addr)
153 case stm8_flash_on: return "Turn ticking of flash on/off (bool, RW)";
155 return "Not used";
160 cl_flash::tick(int cycles)
162 if (state & fs_busy)
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))
170 int i;
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);
175 c->download(0);
177 if (mode == fm_erase)
179 uc->sim->app->debug("FLASH end of erase, finish\n");
180 finish_program(true);
182 else
184 uc->sim->app->debug("FLASH end of erase, cont program\n");
185 state= fs_program;
188 else if (elapsed > tprog)
190 int i;
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;
196 n= org | wbuf[i];
197 c->download(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);
205 return 0;
208 void
209 cl_flash::finish_program(bool ok)
211 if (ok)
212 iapsr->set(iapsr->get() | 0x04);
213 else
214 iapsr->set(iapsr->get() | 0x01);
215 uc->sim->app->debug("FLASH prg finish, OK=%d iapsr=%02x\n", ok, iapsr->get());
216 state= fs_wait_mode;
219 t_mem
220 cl_flash::read(class cl_memory_cell *cell)
222 t_mem v;
224 if (conf(cell, NULL))
225 return cell->get();
227 v= cell->get();
228 if (cell == pukr)
229 v= 0;
230 else if (cell == dukr)
231 v= 0;
232 else if (cell == iapsr)
234 v&= ~0x0a;
235 if (p_unlocked)
236 v|= 0x02;
237 if (d_unlocked)
238 v|= 0x08;
239 if (v & 0x05)
241 uc->sim->app->debug("FLASH read iapsr5 %02x\n",v);
242 //uc->sim->stop(0);
244 // clear of EOP and WR_PG_DIS bits will be done by cl_iapsr_op
245 cell->set(v);
247 return v;
250 void
251 cl_flash::write(class cl_memory_cell *cell, t_mem *val)
253 if (conf(cell, val))
254 return;
256 if (cell == pukr)
258 uc->sim->app->debug("FLASH write-pukr %02x\n",*val);
259 if (p_failed)
261 else if (!puk1st)
263 if (*val == PMASS1)
264 puk1st= true;
265 else
266 p_failed= true;
268 else
270 if (*val == PMASS2)
271 puk1st= false, p_unlocked= true;
272 else
273 puk1st= false, p_failed= true;
275 *val= 0;
277 else if (cell == dukr)
279 uc->sim->app->debug("FLASH write-dukr %02x\n",*val);
280 if (d_failed)
282 else if (!duk1st)
284 if (*val == DMASS1)
285 duk1st= true;
286 else
287 d_failed= true;
289 else
291 if (*val == DMASS2)
292 duk1st= false, d_unlocked= true;
293 else
294 duk1st= false, d_failed= true;
296 *val= 0;
298 else if (cell == iapsr)
300 uc->sim->app->debug("FLASH write-iapsr %02x\n",*val);
301 t_mem org= iapsr->get();
302 // PUL, DUL
303 if (!(*val & 0x02))
304 p_unlocked= puk1st= false;
305 if (!(*val & 0x08))
306 d_unlocked= duk1st= false;
307 *val&= ~0x0a;
308 if (p_unlocked)
309 *val|= 0x02;
310 if (d_unlocked)
311 *val|= 0x08;
312 // HVOFF
313 *val&= ~0x40;
314 // EOP
315 *val&= 0x40;
316 if (org & 0x40)
317 *val|= 0x40;
319 else if (cell == cr2r)
321 uc->sim->app->debug("FLASH write-cr2r %02x\n",*val);
322 *val&= ~0x0e;
323 if (state & fs_busy)
325 *val&= ~0x30;
326 *val|= (cr2r->get() & 0x30);
328 if ((ncr2r == NULL) ||
329 (ncr2r->get() == ((~(*val))&0xff)))
330 set_flash_mode(*val);
332 else if ((ncr2r != NULL) &&
333 (cell == ncr2r))
335 uc->sim->app->debug("FLASH write-ncr2r %02x\n",*val);
336 *val|= 0x0e;
337 if (state & fs_busy)
339 *val&= ~0x30;
340 *val|= (ncr2r->get() & 0x30);
342 if (cr2r->get() == ((~(*val))&0xff))
343 set_flash_mode((~(*val))&0xff);
348 t_mem
349 cl_flash::conf_op(cl_memory_cell *cell, t_addr addr, t_mem *val)
351 switch ((enum stm8_flash_cfg)addr)
353 case stm8_flash_on:
354 if (val)
356 if (*val)
357 on= true;
358 else
359 on= false;
361 else
362 cell->set(on?1:0);
363 break;
364 case stm8_flash_nuof_cfg:
365 break;
367 return cell->get();
371 void
372 cl_flash::flash_write(t_addr a, t_mem val)
374 uc->sim->app->debug("FLASH wr(%06lx,%02x)\n",a,val);
375 if (!uc)
377 uc->sim->app->debug(" no uc\n");
378 return;
380 if (uc->rom == NULL)
382 uc->sim->app->debug(" no rom\n");
383 return;
385 if ((a >= 0x8000) &&
386 !p_unlocked)
388 uc->sim->app->debug(" plocked\n");
389 return;
391 if ((a < 0x8000) &&
392 !d_unlocked)
394 uc->sim->app->debug(" dlocked\n");
395 return;
397 if (state & fs_busy)
399 uc->sim->app->debug(" busy %d\n",state);
400 return;
403 uc->sim->app->debug(" wbuf_start=%06lx\n",wbuf_start);
404 if (wbuf_start == 0)
406 uc->sim->app->debug(" calling start_wbuf(%06lx)\n",a);
407 start_wbuf(a);
410 int offset= a - wbuf_start;
411 uc->sim->app->debug(" offset=%d\n",offset);
412 if (mode == fm_byte)
414 // fixup tprog
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);
419 if (tprog < 6000)
421 if (wbuf[0] ||
422 wbuf[1] ||
423 wbuf[2] ||
424 wbuf[3])
425 tprog= 6000;
427 wbuf[offset]= val;
428 if (tprog < 6000)
429 start_program(fs_program);
431 else if (mode == fm_erase)
433 uc->sim->app->debug(" romwrite in erase mode\n");
434 wbuf[offset]= val;
435 wbuf_writes++;
436 if ((wbuf_writes == 4) &&
437 (((a+1) % 4) == 0))
439 u8_t v= 0;
440 v|= wbuf[0];
441 v|= wbuf[1];
442 v|= wbuf[2];
443 v|= wbuf[3];
444 if (v == 0)
446 uc->sim->app->debug(" starting erase\n");
447 start_program(fs_pre_erase);
451 else
453 wbuf[offset]= val;
454 wbuf_started= true;
455 wbuf_writes++;
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);
462 else
463 start_program(fs_pre_erase);
468 // normal program: 6 ms
469 // fast program: 3 ms
470 // erase: 3 ms
472 void
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 */ )
480 mode= fm_word;
481 tprog= 6000; /* normal mode */
482 wbuf_size= 4;
484 else if (cr2val & 0x20 /* ERASE */ )
486 mode= fm_erase;
487 tprog= 3000;
488 wbuf_size= 128;
490 else if (cr2val & 0x10 /* FPRG */ )
492 mode= fm_fast_block;
493 tprog= 3000;
494 wbuf_size= 128;
496 else if (cr2val & 0x01 /* PRG */ )
498 mode= fm_block;
499 tprog= 6000;
500 wbuf_size= 128;
502 else
504 mode= fm_byte;
505 tprog= fix?6000:3000;
506 wbuf_size= 4;
508 state= fs_wait_data;
509 uc->sim->app->debug("FLASH state=wait_data\n");
510 wbuf_started= false;
511 wbuf_start= 0;
514 void
515 cl_flash::start_wbuf(t_addr addr)
517 int i;
518 wbuf_start= addr - (addr % wbuf_size);
519 wbuf_writes= 0;
520 for (i= 0; i < 256; i++)
521 wbuf[i]= 0;
522 uc->sim->app->debug("FLASH start_wbuf %06lx (wbuf_start=%06lx,size=%d)\n", addr, wbuf_start, wbuf_size);
525 void
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",
529 start_state,
530 wbuf[0], wbuf[1], wbuf[2], wbuf[3]);
531 state= start_state;
532 start_time= uc->ticks->get_rtime();
535 const char *
536 cl_flash::state_name(enum stm8_flash_state s)
538 switch (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";
546 return "unknown";
549 void
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: ");
554 if (p_failed)
555 con->dd_printf("fail");
556 else if (p_unlocked)
557 con->dd_printf("unlocked");
558 else if (puk1st)
559 con->dd_printf("MASS1");
560 else
561 con->dd_printf("locked");
562 con->dd_printf("\n");
564 con->dd_printf("DUK: ");
565 if (d_failed)
566 con->dd_printf("fail");
567 else if (d_unlocked)
568 con->dd_printf("unlocked");
569 else if (duk1st)
570 con->dd_printf("MASS1");
571 else
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);
580 /* SAF */
582 cl_saf_flash::cl_saf_flash(class cl_uc *auc, t_addr abase):
583 cl_flash(auc, abase, "flash")
587 void
588 cl_saf_flash::registration(void)
590 class cl_it_src *is;
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,
600 cr1r,0x02,
601 iapsr,0x04,
602 0x8008+24*4, false, false,
603 "FLASH_EOP", 20*20+0));
604 uc->it_sources->add(is= new cl_it_src(uc, 24,
605 cr1r,0x02,
606 iapsr,0x01,
607 0x8008+24*4, false, false,
608 "FLASH_RO", 20*20+1));
609 is->init();
611 class cl_iapsr_op *o= new cl_iapsr_op(iapsr);
612 iapsr->append_operator(o);
616 /* L,L101 */
618 cl_l_flash::cl_l_flash(class cl_uc *auc, t_addr abase):
619 cl_flash(auc, abase, "flash")
623 void
624 cl_l_flash::registration(void)
626 class cl_it_src *is;
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);
633 ncr2r= NULL;
635 uc->it_sources->add(is= new cl_it_src(uc, 1,
636 cr1r,0x02,
637 iapsr,0x04,
638 0x8008+1*4, false, false,
639 "FLASH_EOP", 20*20+0));
640 uc->it_sources->add(is= new cl_it_src(uc, 1,
641 cr1r,0x02,
642 iapsr,0x01,
643 0x8008+1*4, false, false,
644 "FLASH_RO", 20*20+1));
645 is->init();
649 /* End of stm8.src/flash.cc */