diff options
author | Andrej Shadura <andrewsh@debian.org> | 2018-05-08 15:59:29 +0200 |
---|---|---|
committer | Andrej Shadura <andrewsh@debian.org> | 2018-05-08 15:59:29 +0200 |
commit | 5b8466f7fae0e071c0f4eda13051c93313910028 (patch) | |
tree | 7061957f770e5e245ba00666dad912a2d44e7fdc /lib/simulator/engine/engine_mcu_configuration.tcl |
Import Upstream version 1.3.7
Diffstat (limited to 'lib/simulator/engine/engine_mcu_configuration.tcl')
-rwxr-xr-x | lib/simulator/engine/engine_mcu_configuration.tcl | 555 |
1 files changed, 555 insertions, 0 deletions
diff --git a/lib/simulator/engine/engine_mcu_configuration.tcl b/lib/simulator/engine/engine_mcu_configuration.tcl new file mode 100755 index 0000000..7701583 --- /dev/null +++ b/lib/simulator/engine/engine_mcu_configuration.tcl @@ -0,0 +1,555 @@ +#!/usr/bin/tclsh +# Part of MCU 8051 IDE ( http://mcu8051ide.sf.net ) + +############################################################################ +# Copyright (C) 2007-2009 by Martin Ošmera # +# martin.osmera@gmail.com # +# # +# This program is free software; you can redistribute it and#or modify # +# it under the terms of the GNU General Public License as published by # +# the Free Software Foundation; either version 2 of the License, or # +# (at your option) any later version. # +# # +# This program is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +# GNU General Public License for more details. # +# # +# You should have received a copy of the GNU General Public License # +# along with this program; if not, write to the # +# Free Software Foundation, Inc., # +# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # +############################################################################ + +# -------------------------------------------------------------------------- +# DESCRIPTION +# Part of simulator engine functionality. +# +# -------------------------------------------------------------------------- +# MCU CONFIGURATION RELATED PROCEDURES +# -------------------------------------------------------------------------- + + +## Increment program overall time + # This function also manages watchdog and data EEPROM + # @parm Int num - Number of instruction cycles + # @return Bool - 1 == device reseted; 0 == normal +private method increment_program_time {num} { + # Increment counter of instruction cycles + incr overall_instructions $num + incr run_statistics(2) $num + + # Increment overall time + if {$controllers_conf(X2)} { + set num [expr {$num / 2.0}] + } + set overall_time [expr {$overall_time + $num}] + incr run_statistics(1) [expr {int($num * 12)}] + if {$clock_kHz != 0 && $clock_kHz != {}} { + incr run_statistics(0) [expr {int($num * (12000000.0 / $clock_kHz))}] + } + + eeprom_controller $num + return [watchdog_controller] +} + +## Adjust configuration acording to new value of the given bit + # @parm Int addr - Bit address + # @return void +private method evaluate_bit {addr} { + if {$addr < 128} { + if {$sync_ena} { + $this Simulator_sync_reg [getRegOfBit $addr] + } + } { + evaluate_sfr [getRegOfBit $addr] + } +} + +## Evaluate list of interrupt priorities acording to values of IP and IPH + # @return void +private method evaluate_interrupt_priorities {} { + # Determinate value of Interrupt Priority High register + if {$feature_avaliable(iph)} { + set iph $sfr(183) + } { + set iph 0 + } + + # Lists of priority flags + set ip_0 {} + set ip_1 {} + set ip_2 {} + set ip_3 {} + + # Lists of priority levels + set pl_0 {} + set pl_1 {} + set pl_2 {} + set pl_3 {} + set ip 0 + + # Determinate list of priority flags and priority levels in decremental order + foreach key {PX0 PT0 PX1 PT1 PS PT2 PC} mask {1 2 4 8 16 32 64} { + set ip 0 + if {[expr {$sfr(184) & $mask}]} { + incr ip + } + if {[expr {$iph & $mask}]} { + incr ip 2 + } + switch -- $ip { + 0 {lappend ip_0 $key} + 1 {lappend ip_1 $key} + 2 {lappend ip_2 $key} + 3 {lappend ip_3 $key} + } + lappend pl_${ip} $ip + } + set controllers_conf(IP) [concat $ip_3 $ip_2 $ip_1 $ip_0] + set controllers_conf(IP_level) [concat $pl_3 $pl_2 $pl_1 $pl_0] + + # Determinate list of interrupts flags and priority levels in decremental order + set interrupt_pri_flg {} + set interrupt_pri_num {} + foreach flag $controllers_conf(IP) ip $controllers_conf(IP_level) { + switch -- $flag { + PS { + if {$feature_avaliable(uart)} { + lappend interrupt_pri_flg RI TI + lappend interrupt_pri_num $ip $ip + } + if {$feature_avaliable(spi)} { + lappend interrupt_pri_flg SPIF + lappend interrupt_pri_num $ip + } + } + PT2 { + if {!$feature_avaliable(t2)} {continue} + lappend interrupt_pri_flg EXF2 TF2 + lappend interrupt_pri_num $ip $ip + } + PX0 { + lappend interrupt_pri_flg IE0 + lappend interrupt_pri_num $ip + } + PT0 { + lappend interrupt_pri_flg TF0 + lappend interrupt_pri_num $ip + } + PX1 { + lappend interrupt_pri_flg IE1 + lappend interrupt_pri_num $ip + } + PT1 { + lappend interrupt_pri_flg TF1 + lappend interrupt_pri_num $ip + } + PC { + if {!$feature_avaliable(acomparator)} {continue} + lappend interrupt_pri_flg CF + lappend interrupt_pri_num $ip + } + } + } + + # Adjust interrup monitor + $this interrupt_monitor_intr_prior $interrupt_pri_flg +} + +## Adjust configuration acording to new value of the given SFR + # @parm Int - Register address + # @parm Bool = 1 - Synchronize this SFR with external interface + # @return void +private method evaluate_sfr args { + set addr [lindex $args 0] + set sync [lindex $args 1] + + switch -- $addr { + 135 { ;# PCON 0x87 + set SMOD0_prev $controllers_conf(SMOD0) + + write_conf 135 {SMOD1 SMOD0 PWMEN POF GF1 GF0 PD IDL} + + if {$SMOD0_prev != $controllers_conf(SMOD0)} { + $this simulator_gui_SMOD0_changed + } + } + 168 { ;# IE 0xA8 + write_conf 168 {EA EC ET2 ES ET1 EX1 ET0 EX0} + + # Inform interrupt monitor + $this interrupt_monitor_intr_ena_dis + } + 184 { ;# IP 0xB8 + evaluate_interrupt_priorities + } + 152 { ;# SCON 0x98 + write_conf 152 {- SM1 SM2 REN TB8 RB8 TI RI} + + # Determinate SM0 and FE + if {$controllers_conf(SMOD0)} { + set controllers_conf(FE) [expr {($sfr(152) & 0x80) ? 1 : 0}] + } { + set controllers_conf(SM0) [expr {($sfr(152) & 0x80) ? 1 : 0}] + } + + # Determinate UART operating mode + set UART_M_prev $controllers_conf(UART_M) + set controllers_conf(UART_M) [expr {$controllers_conf(SM0) * 2 + $controllers_conf(SM1)}] + if {$timer_0_running && $UART_M_prev != $controllers_conf(UART_M)} { + $this simulator_invalid_uart_mode_change $pc $Line($pc) + internal_shutdown + } + + # Inform interrupt monitor + $this interrupt_monitor_intr_flags [simulator_get_active_intr_flags] + } + 136 { ;# TCON 0x88 + write_conf 136 {TF1 TR1 TF0 TR0 IE1 IT1 IE0 IT0} + + # Inform interrupt monitor + $this interrupt_monitor_intr_flags [simulator_get_active_intr_flags] + } + 137 { ;# TMOD 0x89 + write_conf 137 {GATE1 CT1 M11 M01 GATE0 CT0 M10 M00} + + set T0_MOD_prev $controllers_conf(T0_MOD) + set T1_MOD_prev $controllers_conf(T1_MOD) + + set controllers_conf(T0_MOD) [expr {$controllers_conf(M10) * 2 + $controllers_conf(M00)}] + set controllers_conf(T1_MOD) [expr {$controllers_conf(M11) * 2 + $controllers_conf(M01)}] + + # Manual: It is important to stop timer/counter before changing modes + if {$timer_0_running && $T0_MOD_prev != $controllers_conf(T0_MOD)} { + $this simulator_invalid_timer_mode_change 0 $pc $Line($pc) + internal_shutdown + } + if {$timer_1_running && $T1_MOD_prev != $controllers_conf(T1_MOD)} { + $this simulator_invalid_timer_mode_change 1 $pc $Line($pc) + internal_shutdown + } + } + 208 { ;# PSW 0xD0 + set bank [expr {($sfr(208) & 24) >> 3}] + } + 224 { ;# A 0xE0 + set A 0 + set count 0 + set mask 1 + for {set i 0} {$i < 8} {incr i} { + if {[expr {$sfr(224) & $mask}] > 0} { + incr count + } + set mask [expr {$mask << 1}] + } + + if {[expr {$count % 2}] == 1} { + setBit $symbol(P) 1 + } { + setBit $symbol(P) 0 + } + } + + 162 { ;# AUXR1 0xA2 + set DPS_org $controllers_conf(DPS) + write_conf 162 {- - - - - - - DPS} + + # Switch visible dual DPTR + if {!$feature_avaliable(hddptr)} { + if {$controllers_conf(DPS)} { + set DPL {DP1L} + set DPH {DP1H} + } { + set DPL {DP0L} + set DPH {DP0H} + } + + # Switch hidden dual DPTR + } elseif {$DPS_org != $controllers_conf(DPS)} { + if {$DPS_org} { + set hidden_DPTR1 [list $sfr($symbol(DP0L)) $sfr($symbol(DP0H))] + } { + set hidden_DPTR0 [list $sfr($symbol(DP0L)) $sfr($symbol(DP0H))] + } + if {$controllers_conf(DPS)} { + set sfr($symbol(DP0L)) [lindex $hidden_DPTR1 0] + set sfr($symbol(DP0H)) [lindex $hidden_DPTR1 1] + } { + set sfr($symbol(DP0L)) [lindex $hidden_DPTR0 0] + set sfr($symbol(DP0H)) [lindex $hidden_DPTR0 1] + } + if {$sync_ena} { + $this Simulator_GUI_sync S $symbol(DP0L) + $this Simulator_GUI_sync S $symbol(DP0H) + } + if {${::Simulator::reverse_run_steps}} { + stepback_reg_change S $symbol(DP0L) + stepback_reg_change S $symbol(DP0H) + } + } + } + 142 { ;# AUXR 0x8E + if {$feature_avaliable(wdtcon)} { + if {$feature_avaliable(intelpe)} { + write_conf 142 {- - - - - - IPE DISALE} + } { + write_conf 142 {- - - - - - EXTRAM DISALE} + } + } { + write_conf 142 {- - - WDIDLE DISRTO - EXTRAM DISALE} + } + } + 166 { ;# WDTRST 0xA6 + if {$controllers_conf(HWDT)} { + if {$sfr(166) == 225 && $wdtrst_prev_val == 30} { + set controllers_conf(WatchDogTimer) 1 + set watchdog_value -$time + + if {$feature_avaliable(wdtcon)} { + set controllers_conf(WDTEN) 1 + set sfr(167) [expr {$sfr(167) | 1}] + if {${::Simulator::reverse_run_steps}} { + stepback_reg_change S 167 + } + if {$sync_ena} { + $this Simulator_GUI_sync S 167 + } + } + } + set wdtrst_prev_val $sfr(166) + } + } + 200 { ;# T2CON 0xC8 + write_conf 200 {TF2 EXF2 RCLK TCLK EXEN2 TR2 CT2 CPRL2} + + # Inform interrupt monitor + $this interrupt_monitor_intr_flags [simulator_get_active_intr_flags] + } + 201 { ;# T2MOD 0xC9 + write_conf 201 {- - - - - - T2OE DCEN} + } + 143 { ;# CLKREG/CKCON 0x8F + write_conf 143 {- - - - - - PWDEX X2} + } + 151 { ;# ACSR 0x97 + write_conf 151 {- - - CF CEN CM2 CM1 CM0} + + set controllers_conf(AC_MOD) [expr { + $controllers_conf(CM0) * 1 + + $controllers_conf(CM1) * 2 + + $controllers_conf(CM2) * 4 + }] + + # Inform interrupt monitor + $this interrupt_monitor_intr_flags [simulator_get_active_intr_flags] + } + 183 { ;# IPH 0xB7 + evaluate_interrupt_priorities + } + 213 { ;# SPCR 0xD5 + write_conf 213 {SPIE SPE DORD MSTR CPOL CPHA SPR1 SPR0} + } + 170 { ;# SPSR 0xAA + write_conf 170 {SPIF WCOL LDEN - - - DISSO ENH} + + # Inform interrupt monitor + $this interrupt_monitor_intr_flags [simulator_get_active_intr_flags] + } + 167 { ;# WDTCON/WDTPRG 0xA7 + if {$feature_avaliable(wdtprg)} { + write_conf 167 {- - - - - PS2 PS1 PS0} + } { + write_conf 167 {PS2 PS1 PS0 WDIDLE DISRTO HWDT WSWRST WDTEN} + } + set controllers_conf(WatchDogPrescaler) 0 + if {$controllers_conf(PS2)} { + incr controllers_conf(WatchDogPrescaler) 4 + } + if {$controllers_conf(PS1)} { + incr controllers_conf(WatchDogPrescaler) 2 + } + if {$controllers_conf(PS0)} { + incr controllers_conf(WatchDogPrescaler) 1 + } + set controllers_conf(WatchDogPrescaler) \ + [expr {int(pow(2,$controllers_conf(WatchDogPrescaler)))}] + } + 150 { ;# EECON 0x96 + set bit_RDYBSY $controllers_conf(RDYBSY) + set bit_WRTINH $controllers_conf(WRTINH) + + write_conf 150 {- - EELD EEMWE EEMEN DPS RDYBSY WRTINH} + + # Bits RDYBSY and WRTINH are READ-ONLY + if { + $controllers_conf(RDYBSY) != $bit_RDYBSY + || + $controllers_conf(WRTINH) != $bit_WRTINH + } then { + set sfr(150) [expr {(($sfr(150) & 0xFC) | $bit_RDYBSY * 2) | $bit_WRTINH}] + } + set controllers_conf(RDYBSY) $bit_RDYBSY + set controllers_conf(WRTINH) $bit_WRTINH + + if {$controllers_conf(DPS)} { + set DPL {DP1L} + set DPH {DP1H} + } { + set DPL {DP0L} + set DPH {DP0H} + } + } + default { ;# Nothing to do ... + } + } + + # Synchronize with an external interface + if {$sync_ena && $sync != {0}} { + $this Simulator_GUI_sync S $addr + } +} + +## Modify configuration + # @parm Int addr - Source register + # @parm List key_list - List of keys for array controllers_conf + # @return void +private method write_conf {addr key_list} { + set mask 256 + foreach key $key_list { + + set mask [expr {$mask >> 1}] + if {$key == {-}} {continue} + + if {[expr {$sfr($addr) & $mask}] == 0} { + set controllers_conf($key) 0 + } { + set controllers_conf($key) 1 + } + } +} + +## Increment program counter + # @parm Int val - Value to increment by + # @return void +private method incr_pc {val} { + set pc [incr_16b $pc $val] +} + +## Increment 16 bit value + # @parm Int val - Value to increment + # @parm Int byVal - Value to increment by + # @return Int - 16 bit result +private method incr_16b {val byVal} { + incr val $byVal + if {$val > 65535} { + incr val -65536 + } elseif {$val < 0} { + incr val 65536 + } + return $val +} + +## Increment 8 bit value + # @parm Char type - D == Direct addressing; I == Indirect addressing + # @parm Int addr - Register to increment + # @parm Int val - Value to increment by + # @return Bool - 0 == successful; 1 == failed +private method incr_8b {type addr val} { + if {[check_address_validity $type $addr]} {return 1} + + # Indirect addressing + if {$type == {I} || $addr < 128} { + if {${::Simulator::reverse_run_steps}} { + stepback_reg_change I $addr + } + + incr ram($addr) $val + if {$ram($addr) > 255} { + incr ram($addr) -256 + } elseif {$ram($addr) < 0} { + incr ram($addr) 256 + } + if {$sync_ena} { + $this Simulator_sync_reg $addr + } + + # Direct addressing + } else { + if {${::Simulator::reverse_run_steps}} { + stepback_reg_change S $addr + } + + incr sfr($addr) $val + set val [read_sfr $addr] + if {$val > 255} { + incr sfr($addr) -256 + } elseif {$val < 0} { + incr sfr($addr) 256 + } + if {$sync_ena} { + $this Simulator_GUI_sync S $addr + } + } + return 0 +} + +## Pop value from stack + # @return Int - result +private method stack_pop {} { + if {[check_address_validity I $sfr(129)]} { + set result [undefined_octet] + } { + if {${::Simulator::reverse_run_steps}} { + stepback_reg_change I $sfr(129) + } + set result $ram($sfr(129)) ;# 129d == 0x81 == SP + } + if {${::Simulator::reverse_run_steps}} { + stepback_reg_change S 129 + } + incr sfr(129) -1 + if {$sfr(129) < 0} { + set sfr(129) 255 + if {!${::Simulator::ignore_stack_underflow}} { + $this simulator_stack_warning under $pc [lindex $Line($pc) 0] + internal_shutdown + } + } + + evaluate_sfr 129 + $this stack_monitor_pop + + return $result +} + +## Push value onto stack + # @parm Int - Value to push onto stack + # @return void +public method stack_push {val} { + if {${::Simulator::reverse_run_steps}} { + stepback_reg_change S 129 + } + incr sfr(129) ;# 129d == 0x81 == SP + if {$sfr(129) > 255} { + set sfr(129) 0 + if {!${::Simulator::ignore_stack_overflow}} { + $this simulator_stack_warning over $pc [lindex $Line($pc) 0] + internal_shutdown + } + } + if {[check_address_validity I $sfr(129)]} { + return + } { + if {${::Simulator::reverse_run_steps}} { + stepback_reg_change I $sfr(129) + } + set ram($sfr(129)) $val + if {$sync_ena} { + $this Simulator_sync_reg $sfr(129) + } + } + + evaluate_sfr 129 + $this stack_monitor_push $sfr(129) $val +} |