gaochunhui hace 1 año
commit
7d755419f8
Se han modificado 81 ficheros con 18033 adiciones y 0 borrados
  1. 12 0
      .gitignore
  2. 26 0
      boot.ve
  3. 50 0
      logic/af_ip.tcl
  4. 50 0
      logic/af_quartus.tcl
  5. 350 0
      logic/af_run.tcl
  6. 12 0
      logic/boot.asf
  7. BIN
      logic/boot.bin
  8. 24 0
      logic/boot.hx
  9. 248 0
      logic/boot.inc
  10. 2 0
      logic/boot.post.asf
  11. 6 0
      logic/boot.pre.asf
  12. 40 0
      logic/boot.proj
  13. 3 0
      logic/boot.qpf
  14. 141 0
      logic/boot.qsf
  15. BIN
      logic/boot.qws
  16. 13 0
      logic/boot.sdc
  17. 362 0
      logic/boot.v
  18. 728 0
      logic/boot_assignment_defaults.qdf
  19. 35 0
      logic/boot_ip.v
  20. 1536 0
      logic/boot_routed.v
  21. 367 0
      logic/logic_log.txt
  22. 91 0
      platformio.ini
  23. 453 0
      src/at24cXX.c
  24. 45 0
      src/at24cXX.h
  25. 401 0
      src/bsp.c
  26. 113 0
      src/bsp.h
  27. 29 0
      src/delay.c
  28. 16 0
      src/delay.h
  29. 248 0
      src/fpga_boot.inc
  30. 268 0
      src/hamming.c
  31. 22 0
      src/hamming.h
  32. 247 0
      src/key.c
  33. 59 0
      src/key.h
  34. 19 0
      src/led.c
  35. 15 0
      src/led.h
  36. 70 0
      src/main.c
  37. 488 0
      src/master/components/atomlib/ustdio.c
  38. 91 0
      src/master/components/atomlib/ustdio.h
  39. 169 0
      src/master/components/ringBuffer/ringBuffer.c
  40. 29 0
      src/master/components/ringBuffer/ringBuffer.h
  41. 309 0
      src/master/user/app/bspatch.c
  42. 47 0
      src/master/user/app/bspatch.h
  43. 479 0
      src/master/user/app/iap.c
  44. 33 0
      src/master/user/app/iap.h
  45. 536 0
      src/master/user/app/ota_flash.c
  46. 82 0
      src/master/user/app/ota_flash.h
  47. 87 0
      src/master/user/app/vFile.c
  48. 24 0
      src/master/user/app/vFile.h
  49. 360 0
      src/master/user/app/ymodem.c
  50. 67 0
      src/master/user/app/ymodem.h
  51. 66 0
      src/master/user/db/db.c
  52. 26 0
      src/master/user/db/db.h
  53. 285 0
      src/master/user/inc/BIN.H
  54. 77 0
      src/master/user/inc/stm32f10x_conf.h
  55. 54 0
      src/master/user/inc/stm32f10x_it.h
  56. 78 0
      src/master/user/inc/type.h
  57. 51 0
      src/master/user/inc/usr_cfg.h
  58. 89 0
      src/master/user/lib/crc32.c
  59. 9 0
      src/master/user/lib/crc32.h
  60. 610 0
      src/master/user/lib/mylib.c
  61. 44 0
      src/master/user/lib/mylib.h
  62. 375 0
      src/master/user/lzma/7zTypes.h
  63. 33 0
      src/master/user/lzma/Compiler.h
  64. 1128 0
      src/master/user/lzma/LzFind.c
  65. 121 0
      src/master/user/lzma/LzFind.h
  66. 57 0
      src/master/user/lzma/LzHash.h
  67. 1209 0
      src/master/user/lzma/LzmaDec.c
  68. 234 0
      src/master/user/lzma/LzmaDec.h
  69. 2991 0
      src/master/user/lzma/LzmaEnc.c
  70. 76 0
      src/master/user/lzma/LzmaEnc.h
  71. 11 0
      src/master/user/lzma/Precomp.h
  72. 138 0
      src/master/user/lzma/lzma_decompress.c
  73. 18 0
      src/master/user/lzma/lzma_decompress.h
  74. 145 0
      src/myflash.c
  75. 19 0
      src/myflash.h
  76. 545 0
      src/ota.c
  77. 166 0
      src/ota.h
  78. 41 0
      src/uart.c
  79. 7 0
      src/uart.h
  80. 370 0
      src/update.c
  81. 58 0
      src/update.h

+ 12 - 0
.gitignore

@@ -0,0 +1,12 @@
+.pio
+.vscode/.browse.c_cpp.db*
+.vscode/c_cpp_properties.json
+.vscode/launch.json
+.vscode/ipch
+*.json
+logic/alta_db
+logic/alta_logs
+logic/db
+logic/incremental_db
+logic/quartus_logs
+logic/simulation

+ 26 - 0
boot.ve

@@ -0,0 +1,26 @@
+SYSCLK 120
+
+HSECLK 8
+
+# 串口
+#调试串口
+UART0_UARTRXD   PIN_69
+UART0_UARTTXD   PIN_68
+
+#i2c eeprom
+GPIO2_0         PIN_97 #I2C_WP
+GPIO2_1         PIN_95 #I2C_SCL
+GPIO2_2         PIN_96 #I2C_SDA
+
+#led
+GPIO1_0 PIN_2 #MCU_RUN
+GPIO1_1 PIN_3 #MCU_MOD
+GPIO1_3 PIN_1 #LORA_STATE
+
+#按键
+GPIO1_4 PIN_92 #MCU_KEY1
+GPIO1_5 PIN_91 #MCU_KEY2
+GPIO1_6 PIN_88 #MCU_KEY3
+
+
+

+ 50 - 0
logic/af_ip.tcl

@@ -0,0 +1,50 @@
+set AGM_SUPRA true
+set DESIGN "boot"
+set IPLIST {alta_bram alta_bram9k alta_sram alta_wram alta_pll alta_pllx alta_pllv alta_pllve alta_boot alta_osc alta_mult alta_multm alta_ufm alta_ufms alta_ufml alta_i2c alta_spi alta_irda alta_mcu alta_mcu_m3 alta_saradc alta_adc alta_dac alta_cmp }
+lappend IPLIST alta_rv32
+
+proc set_alta_partition {inst tag} {
+  set full_name [get_name_info -observable_type pre_synthesis -info full_path $inst]
+  set inst_name [get_name_info -observable_type pre_synthesis -info short_full_path $inst]
+  set base_name [get_name_info -observable_type pre_synthesis -info instance_name $inst]
+  set section_id [string map { [ _ ] _ . _ | _} $inst_name]
+  eval "set_global_assignment -name PARTITION_COLOR 52377 -section_id $section_id -tag $tag"
+  eval "set_global_assignment -name PARTITION_NETLIST_TYPE SOURCE -section_id $section_id -tag $tag"
+  eval "set_global_assignment -name PARTITION_FITTER_PRESERVATION_LEVEL PLACEMENT_AND_ROUTING -section_id $section_id -tag $tag"
+  eval "set_instance_assignment -name PARTITION_HIERARCHY $section_id -to $full_name -section_id $section_id -tag $tag"
+}
+
+load_package flow
+if { $DESIGN == "" } {
+  set DESIGN $::quartus(args)
+}
+project_open $DESIGN
+
+set tag alta_auto
+if { [llength $IPLIST] > 0 } {
+  # A Quartus bug saves PARTITION_HIERARCHY assignments without tag. Use section_id to remove them.
+  set asgn_col [get_all_global_assignments -name PARTITION_NETLIST_TYPE -tag $tag]
+  foreach_in_collection part $asgn_col {
+    set section_id [lindex $part 0]
+    eval "remove_all_instance_assignments -name PARTITION_HIERARCHY -section_id $section_id"
+  }
+  eval "remove_all_global_assignments -name PARTITION_COLOR -tag $tag"
+  eval "remove_all_global_assignments -name PARTITION_NETLIST_TYPE -tag $tag"
+  eval "remove_all_global_assignments -name PARTITION_FITTER_PRESERVATION_LEVEL -tag $tag"
+  catch { execute_module -tool map }
+
+  foreach ip $IPLIST {
+    foreach_in_collection inst [get_names -node_type hierarchy -observable_type pre_synthesis -filter "$ip:*"] {
+      set_alta_partition $inst $tag
+    }
+    foreach_in_collection inst [get_names -node_type hierarchy -observable_type pre_synthesis -filter "*|$ip:*"] {
+      set_alta_partition $inst $tag
+    }
+  }
+}
+eval "set_global_assignment -name EDA_MAINTAIN_DESIGN_HIERARCHY PARTITION_ONLY -section_id eda_simulation"
+
+project_close
+
+exit
+

+ 50 - 0
logic/af_quartus.tcl

@@ -0,0 +1,50 @@
+set AGM_SUPRA true
+set RETRY 0
+set DESIGN "boot"
+
+if { [is_project_open] } {
+  export_assignments
+}
+
+set is_compatible false
+if { $is_compatible } {
+  cd 
+  qexec "[file join $::quartus(binpath) quartus_eda] $DESIGN --simulation --tool=modelsim --format=verilog"
+} else {
+  set FITTER_EFFORTS    {"STANDARD FIT" "STANDARD FIT" "FAST FIT" "FAST FIT" "FAST FIT"}
+  set SEEDS             [list [expr int(rand()*100)] \
+                              [expr int(rand()*100)] \
+                              [expr int(rand()*100)] \
+                              [expr int(rand()*100)] \
+                              [expr int(rand()*100)]]
+  set PLACEMENT_EFFORTS [list [expr rand()*5+0.1] \
+                              [expr rand()*5+0.1] \
+                              [expr rand()*5+0.1] \
+                              [expr rand()*5+0.1] \
+                              [expr rand()*5+0.1]]
+  set    ROUTER_EFFORTS [list [expr rand()*5+0.25] \
+                              [expr rand()*5+0.25] \
+                              [expr rand()*5+0.25] \
+                              [expr rand()*5+0.25] \
+                              [expr rand()*5+0.25]]
+
+  qexec "[file join $::quartus(binpath) quartus_sh] -t af_ip.tcl"
+
+  load_package flow
+  project_open $DESIGN
+
+  set RETRY [expr $RETRY<[llength $FITTER_EFFORTS]?$RETRY:[llength $FITTER_EFFORTS]]
+  for {set nn -1} {$nn < $RETRY} {incr nn} {
+    if {$nn >= 0}  {
+      set_global_assignment -name FITTER_EFFORT \"[lindex $FITTER_EFFORTS $nn]\"
+      set_global_assignment -name SEED [lindex $SEEDS $nn]
+      set_global_assignment -name PLACEMENT_EFFORT_MULTIPLIER [lindex $PLACEMENT_EFFORTS $nn]
+      set_global_assignment -name    ROUTER_EFFORT_MULTIPLIER [lindex    $ROUTER_EFFORTS $nn]
+    }
+
+    set code [catch {execute_flow -compile} msg]
+    if { $code == 0 } { break }
+  }
+}
+
+

+ 350 - 0
logic/af_run.tcl

@@ -0,0 +1,350 @@
+set ALTA_SUPRA true
+set sh_continue_on_error false
+set sh_echo_on_source  true
+set sh_quiet_on_source true
+set cc_critical_as_fatal true
+set rt_incremental_route true
+set ta_report_auto 1
+set ta_report_auto_constraints $ta_report_auto
+
+if { ! [info exists RESULT_DIR] } {
+  set RESULT_DIR "."
+} elseif { ! [info exists alta_work] } {
+  set alta_work [file join ${RESULT_DIR} alta_db]
+}
+if { ! [info exists DEVICE] } {
+  set DEVICE "AGRV2KL100"
+}
+if { [info exists DESIGN] && ! [info exists TOP_MODULE] } {
+  set TOP_MODULE "$DESIGN"
+}
+if { ! [info exists DESIGN] } {
+  set DESIGN "boot"
+}
+if { ! [info exists TOP_MODULE] } {
+  set TOP_MODULE "top"
+}
+if { ! [info exists IP_FILES] } {
+  set IP_FILES {}
+}
+if { ! [info exists VE_FILE] } {
+  set VE_FILE ""
+}
+if { ! [info exists TIMING_DERATE] } {
+  set TIMING_DERATE {1.000000 1.000000}
+}
+if { [info exists NO_ROUTE] && $NO_ROUTE } {
+  set no_route "-no_route"
+} else {
+  set no_route ""
+}
+if { ! [info exists RETRY] } { set RETRY 0 }
+if { ! [info exists SEED ] } { set SEED 666 }
+set seed_rand ""
+if { $SEED == 0 } { set seed_rand "-seed_rand" }
+if { [info exists QUARTUS_SDC] } {
+  set sdc_remove_quartus_column_name $QUARTUS_SDC
+}
+if { ! [info exists ORG_PLACE] } { set ORG_PLACE false }
+if { ! [info exists MODE] } { set MODE "QUARTUS" }
+if { ! [info exists FLOW] } { set FLOW "ALL"    }
+if { $FLOW == "PROBE" } {
+  if { ! [info exists PROBE_FORCE] } { set PROBE_FORCE false }
+  if { ! [info exists PREFIX] } { set PREFIX "probe_" }
+}
+if { ! [info exists PREFIX] } {
+  set RESULT $DESIGN
+} else {
+  set RESULT $PREFIX$DESIGN
+}
+if { $FLOW == "GEN" || $FLOW == "PACK" || $FLOW == "LOAD" } { set no_route "-no_route" }
+set RUN "run"
+if { $FLOW == "CHECK" } {
+  set RUN "check"
+} elseif { $FLOW == "PROBE" } {
+  set RUN "probe"
+} elseif { $FLOW == "GEN" } {
+  set RUN "gen"
+}
+
+if { ! [info exists alta_logs] } {
+  set alta_logs [file join ${RESULT_DIR} alta_logs]
+}
+file mkdir $alta_logs
+alta::begin_log_cmd [file join $alta_logs ${RUN}.log] [file join $alta_logs ${RUN}.err]
+alta::tcl_whisper "Cmd : [alta::prog_path] [alta::prog_version]([alta::prog_subversion])\n"
+alta::tcl_whisper "Args : [string map {\{ \" \} \"} $tcl_cmd_args]\n"
+
+set_seed_rand $SEED
+set ar_timing_derate ${TIMING_DERATE}
+
+date_time
+if { [file exists [file join . ${DESIGN}.pre.asf]] } {
+  alta::tcl_highlight "Using pre-ASF file ${DESIGN}.pre.asf.\n"
+  source [file join . ${DESIGN}.pre.asf]
+}
+
+set LOAD_DB    false
+set LOAD_PLACE false
+set LOAD_ROUTE false
+if { $FLOW == "LOAD" || $FLOW == "CHECK" || $FLOW == "PROBE" } {
+  set LOAD_DB    true
+  set LOAD_PLACE true
+  set LOAD_ROUTE true
+} elseif { $FLOW == "R" || $FLOW == "ROUTE" } {
+  set LOAD_DB    true
+  set LOAD_PLACE true
+}
+
+set ORIGINAL_QSF "./boot.qsf"
+set ORIGINAL_PIN ""
+
+#################################################################################
+
+while (1) {
+if { [info exists CORNER] } { set_mode -corner $CORNER; }
+
+eval "load_architect ${no_route} -type ${DEVICE} 1 1 1000 1000"
+foreach ip_file $IP_FILES { read_ip $ip_file; }
+
+
+if { $FLOW == "GEN" } {
+  if { ! [info exists CONFIG_BITS] } {
+    set CONFIG_BITS [file join ${RESULT_DIR} ${DESIGN}.bin]
+  }
+  if { [llength $CONFIG_BITS] > 1 } {
+    if { ! [info exists BOOT_BINARY] } {
+      set BOOT_BINARY [file join ${RESULT_DIR} ${DESIGN}_boot.bin]
+    }
+    if { ! [info exists CONFIG_ADDRESSES] } {
+      set CONFIG_ADDRESSES ""
+    }
+    generate_binary -master $BOOT_BINARY -inputs $CONFIG_BITS -address $CONFIG_ADDRESSES
+  } else {
+    set CONFIG_ROOT   [file rootname [lindex $CONFIG_BITS 0]]
+    set SLAVE_RBF     "${CONFIG_ROOT}_slave.rbf"
+    set MASTER_BINARY "${CONFIG_ROOT}_master.bin"
+    if { [file exists [lindex $CONFIG_BITS 0]] } {
+      generate_binary -slave  $SLAVE_RBF     -inputs [lindex $CONFIG_BITS 0] -reverse
+      generate_binary -master $MASTER_BINARY -inputs [lindex $CONFIG_BITS 0]
+    }
+    if { ! [info exists BOOT_BINARY] } {
+      set BOOT_BINARY $MASTER_BINARY
+    }
+  }
+  set PRG_FILE [file rootname $BOOT_BINARY].prg
+  set AS_FILE  [file rootname $BOOT_BINARY]_as.prg
+  generate_programming_file $BOOT_BINARY -erase $ERASE \
+                            -program $PROGRAM -verify $VERIFY -offset $OFFSET \
+                            -prg $PRG_FILE -as $AS_FILE
+  break
+}
+
+if { $LOAD_DB } {
+  load_db -top ${TOP_MODULE}
+  set sdc [file join . ${DESIGN}.adc]
+  if { ! [file exists $sdc] } { set sdc [file join . ${DESIGN}.sdc]; }
+  if { [file exists $sdc] } { read_sdc $sdc; }
+
+} elseif { $MODE == "QUARTUS" } {
+  set verilog ${DESIGN}.vo
+  set is_migrated false
+  if { ! [file exists $verilog] } {
+    set verilog [file join . simulation modelsim ${DESIGN}.vo]
+    set is_migrated true
+  }
+  if { ! [file exists $verilog] } {
+    error "Can not find design verilog file $verilog"
+  }
+  alta::tcl_highlight "Using design verilog file $verilog.\n"
+  set ret [read_design -top ${TOP_MODULE} -ve $VE_FILE -qsf $ORIGINAL_QSF $verilog -hierachy 1]
+  if { !$ret } { exit -1; }
+
+  set sdc [file join . ${DESIGN}.adc]
+  if { ! [file exists $sdc] } { set sdc [file join . ${DESIGN}.sdc]; }
+  if { ! [file exists $sdc] } {
+    alta::tcl_warn "Can not find design SDC file $sdc"
+  } else {
+    alta::tcl_highlight "Using design SDC file $sdc.\n"
+    read_sdc $sdc
+  }
+
+} elseif { $MODE == "SYNPLICITY" || $MODE == "NATIVE" } {
+  set db_gclk_assignment_level 2
+  set verilog ${DESIGN}.vqm
+  set is_migrated false
+  if { ! [file exists $verilog] } {
+    error "Can not find design verilog file $verilog"
+  }
+
+  set sdc [file join . ${DESIGN}.adc]
+  if { ! [file exists $sdc] } { set sdc [file join . ${DESIGN}.sdc]; }
+  alta::tcl_highlight "Using design verilog file $verilog.\n"
+  if { ! [file exists $sdc] } {
+    alta::tcl_warn "Can not find design SDC file $sdc"
+    set ret [read_design_and_pack -sdc $sdc  -top ${TOP_MODULE} $verilog]
+  } else {
+    alta::tcl_highlight "Using design SDC file $sdc.\n"
+    set ret [read_design_and_pack -top ${TOP_MODULE} $verilog]
+  }
+  if { !$ret } { exit -1; }
+
+} else {
+  error "Unsupported mode $MODE"
+}
+
+if { $FLOW == "PACK" } { break }
+
+if { [info exists FITTING] } {
+  if { $FITTING == "Auto" } { set FITTING auto; }
+  set_mode -fitting $FITTING
+}
+if { [info exists FITTER] } {
+  if { $FITTER == "Auto" } {
+    if { $MODE == "QUARTUS" } { set FITTER hybrid; } else { set FITTER full; }
+  }
+  if { $MODE == "SYNPLICITY" || $MODE == "NATIVE" } { set FITTER full; }
+  set_mode -fitter $FITTER
+}
+if { [info exists EFFORT] } { set_mode -effort $EFFORT; }
+if { [info exists SKEW  ] } { set_mode -skew   $SKEW  ; }
+if { [info exists SKOPE ] } { set_mode -skope  $SKOPE ; }
+if { [info exists HOLDX ] } { set_mode -holdx  $HOLDX; }
+if { [info exists TUNING] } { set_mode -tuning $TUNING; }
+if { [info exists TARGET] } { set_mode -target $TARGET; }
+if { [info exists PRESET] } { set_mode -preset $PRESET; }
+if { [info exists ADJUST] } { set pl_criticality_wadjust $ADJUST; }
+
+set alta_aqf [file join $::alta_work alta.aqf]
+if { $LOAD_DB } {
+  # Empty
+} elseif { true } {
+  if { $ORIGINAL_PIN != "" } {
+    if { [file exists $VE_FILE] } {
+      set ORIGINAL_PIN ""
+    } elseif { $ORIGINAL_PIN == "-" } {
+      set ORIGINAL_PIN ""
+    } elseif { ! [file exists $ORIGINAL_PIN] } {
+      if { $is_migrated } {
+        error "Can not find design PIN file $ORIGINAL_PIN, please compile design first"
+      }
+      set ORIGINAL_PIN ""
+    }
+  }
+  if { $ORIGINAL_QSF != "" } {
+    if { $ORIGINAL_QSF == "-" } {
+      set ORIGINAL_QSF ""
+    } elseif { ! [file exists $ORIGINAL_QSF] } {
+      if { $is_migrated } {
+        error "Can not find design exported QSF file $ORIGINAL_QSF, please export assigments first"
+      }
+    }
+  }
+  alta::convert_quartus_settings_cmd $ORIGINAL_QSF $ORIGINAL_PIN $alta_aqf
+}
+if { [file exists "$alta_aqf"] } {
+  alta::tcl_highlight "Using AQF file $alta_aqf.\n"
+  source "$alta_aqf"
+}
+if { [file exists [file join . ${DESIGN}.asf]] } {
+  alta::tcl_highlight "Using ASF file ${DESIGN}.asf.\n"
+  source [file join . ${DESIGN}.asf]
+}
+
+if { $FLOW == "PROBE" } {
+  set ret [place_pseudo -user_io -place_io -place_pll -place_gclk]
+  if { !$ret } { exit -1 }
+
+  set force ""
+  if { [info exists PROBE_FORCE] && $PROBE_FORCE } { set force "-force" }
+  eval "probe_design -froms {${PROBE_FROMS}} -tos {${PROBE_TOS}} ${force}"
+
+} elseif { $FLOW == "CHECK" } {
+  set ret [place_pseudo -user_io -place_io -place_pll -place_gclk]
+  if { !$ret } { exit -1 }
+
+  if { [file exists [file join . ${DESIGN}.chk]] } {
+    alta::tcl_highlight "Using CHK file ${DESIGN}.chk.\n"
+    source [file join . ${DESIGN}.chk]
+    place_design -dry
+    check_design -rule led_guide
+  } else {
+    error "Can not find design CHECK file ${DESIGN}.chk"
+  }
+
+} else {
+  set ret [place_pseudo -user_io -place_io -place_pll -place_gclk -warn_io]
+  if { !$ret } { exit -1 }
+
+  set org_place ""
+  set load_place ""
+  set load_route ""
+  set quiet ""
+  if {  $ORG_PLACE } { set  org_place "-org_place" ; }
+  if { $LOAD_PLACE } { set load_place "-load_place"; }
+  if { $LOAD_ROUTE } { set load_route "-load_route"; }
+  eval "place_and_route_design $org_place $load_place $load_route \
+                               -retry $RETRY $seed_rand $quiet"
+}
+
+date_time
+if { $FLOW != "CHECK" } {
+if { $FLOW != "PROBE" } {
+report_timing -verbose 2 -setup -file $::alta_work/setup.rpt.gz
+report_timing -verbose 1 -setup -file $::alta_work/setup_summary.rpt
+report_timing -verbose 2 -hold -file $::alta_work/hold.rpt.gz
+report_timing -verbose 1 -hold -file $::alta_work/hold_summary.rpt
+
+set ta_report_auto_constraints 0
+report_timing -fmax -file $::alta_work/fmax.rpt
+report_timing -xfer -file $::alta_work/xfer.rpt
+set ta_report_auto_constraints $ta_report_auto
+
+set ta_dump_uncovered 1
+report_timing -verbose 1 -coverage >! $::alta_work/coverage.rpt.gz
+set ta_dump_uncovered -1
+
+
+if { ! [info exists rt_report_timing_fast] } {
+  set rt_report_timing_fast false
+}
+if { $rt_report_timing_fast } {
+  set_timing_corner fast
+  route_delay -quiet
+  report_timing -verbose 2 -setup -file $::alta_work/setup_fast.rpt.gz
+  report_timing -verbose 1 -setup -file $::alta_work/setup_fast_summary.rpt
+  report_timing -verbose 2 -hold -file $::alta_work/hold_fast.rpt.gz
+  report_timing -verbose 1 -hold -file $::alta_work/hold_fast_summary.rpt
+  set ta_report_auto_constraints 0
+  report_timing -fmax -file $::alta_work/fmax_fast.rpt
+  report_timing -xfer -file $::alta_work/xfer_fast.rpt
+  set ta_report_auto_constraints $ta_report_auto
+}
+
+write_routed_design "${RESULT_DIR}/${RESULT}_routed.v"
+}
+
+bitgen normal -prg "${RESULT_DIR}/${RESULT}.prg" -bin "${RESULT_DIR}/${RESULT}.bin"
+if { true } {
+alta::bin_to_asc "${RESULT_DIR}/${RESULT}.bin" "${RESULT_DIR}/${RESULT}.inc"
+} else {
+bitgen sram -prg "${RESULT_DIR}/${RESULT}_sram.prg"
+bitgen download -bin "${RESULT_DIR}/${RESULT}.bin" -svf "${RESULT_DIR}/${RESULT}_download.svf"
+generate_binary -slave "${RESULT_DIR}/${RESULT}_slave.rbf" \
+                -inputs "${RESULT_DIR}/${RESULT}.bin" -reverse
+generate_binary -master "${RESULT_DIR}/${RESULT}_master.bin" \
+                -inputs "${RESULT_DIR}/${RESULT}.bin"
+generate_programming_file "${RESULT_DIR}/${RESULT}_master.bin" -prg "${RESULT_DIR}/${RESULT}_master.prg" \
+  -as "${RESULT_DIR}/${RESULT}_master_as.prg" -hybrid "${RESULT_DIR}/${RESULT}_hybrid.prg"
+}
+}
+break
+}
+
+if { [file exists "./${DESIGN}.post.asf"] } {
+  alta::tcl_highlight "Using post-ASF file ${DESIGN}.post.asf.\n"
+  source "./${DESIGN}.post.asf"
+}
+date_time
+exit
+

+ 12 - 0
logic/boot.asf

@@ -0,0 +1,12 @@
+# pio_begin  >>>>>> DO NOT MODIFY THIS SECTION! >>>>>>
+if { [info exists BOARD_PLL_CLKIN] } {
+  if { $BOARD_PLL_CLKIN == "PIN_OSC" } {
+    set_config -loc 18 0 0 CFG_RCOSC_EN 1'b1
+  }
+}
+if { [info exists USB0_MODE] } {
+  alta::tcl_info "USB0_MODE = $USB0_MODE"
+  set_config -loc 0 1 3 CFG_PULLUP_ENB 1'b0
+  set_config -loc 0 1 3 CFG_PULLDN_ENB 1'b0
+}
+# pio_end    <<<<<< DO NOT MODIFY THIS SECTION! <<<<<<

BIN
logic/boot.bin


+ 24 - 0
logic/boot.hx

@@ -0,0 +1,24 @@
+#ifndef _AGM_BOARD_INFO
+#define _AGM_BOARD_INFO
+
+#ifndef BOARD_HSI_FREQUENCY
+#define BOARD_HSI_FREQUENCY 10000000
+#endif
+
+#ifndef BOARD_HSE_FREQUENCY
+#define BOARD_HSE_FREQUENCY 8000000
+#endif
+
+#ifndef BOARD_PLL_FREQUENCY
+#define BOARD_PLL_FREQUENCY 120000000
+#endif
+
+#ifndef BOARD_BUS_FREQUENCY
+#define BOARD_BUS_FREQUENCY 120000000
+#endif
+
+#ifndef BOARD_PLL_CLKIN
+#define BOARD_PLL_CLKIN PIN_HSE
+#endif
+
+#endif

+ 248 - 0
logic/boot.inc

@@ -0,0 +1,248 @@
+0x40,0x20,0x00,0x01,0x00,0x00,0xff,0xff,0x51,0x00,0x00,0x02,0x00,0x00,0x0c,0x82,
+0x20,0x04,0x00,0x80,0x08,0x08,0x4c,0x2e,0x1b,0x0a,0x86,0x43,0xa2,0x51,0x14,0x20,
+0x81,0x42,0x00,0x20,0x04,0x00,0x80,0x18,0xc8,0x42,0x07,0x11,0x88,0x43,0xe1,0x24,
+0x00,0x04,0x6c,0x02,0x08,0x93,0x21,0x00,0x08,0x41,0x08,0x20,0x85,0x2c,0x97,0x4c,
+0x24,0x51,0x48,0x5c,0x4e,0x69,0x38,0x9b,0xce,0xa5,0x30,0x30,0x04,0x08,0x00,0x21,
+0x81,0xbb,0x84,0x02,0x99,0x2c,0x12,0x7b,0x3d,0x00,0xbf,0x9f,0xe7,0xf5,0xfb,0x7d,
+0xde,0xf7,0x7d,0xbf,0x61,0x85,0xc1,0x70,0x7d,0xde,0xf9,0x03,0x29,0x20,0x73,0xf0,
+0x00,0x30,0x5a,0x7f,0x10,0x3f,0xec,0x6f,0xf7,0x85,0x22,0xcf,0x68,0xb4,0xda,0x80,
+0x16,0x4b,0x6d,0xba,0xdf,0x70,0xb8,0xdc,0xae,0x77,0x4b,0xad,0xb6,0xd9,0x64,0xb3,
+0x5a,0xef,0x77,0xcb,0xb5,0xfa,0xff,0x80,0xc0,0xdd,0xed,0xb7,0xab,0xe6,0x1a,0xd1,
+0x82,0xc4,0xe2,0xb1,0x6f,0xfb,0xc5,0x8e,0xcc,0xc0,0x40,0x40,0xc1,0x93,0xc0,0x06,
+0x47,0x27,0x95,0xcb,0xd7,0xb3,0x39,0x2c,0x66,0x7b,0x3f,0x73,0xc7,0x59,0x70,0xfa,
+0x4a,0x46,0x83,0x4f,0xa8,0xc6,0xe1,0x32,0xd9,0x2c,0xdc,0xf7,0x35,0x94,0xd7,0xeb,
+0x76,0x30,0x3c,0xbe,0xa7,0x6f,0x8c,0xd1,0x61,0x74,0xb8,0x7d,0xc6,0xfb,0x05,0xba,
+0xcb,0x4f,0x76,0x9a,0xcc,0xc6,0xcb,0x8d,0xb5,0xce,0xef,0xf9,0x77,0x6e,0x0e,0xf3,
+0x49,0xcc,0xe8,0xe8,0x75,0x7b,0x0c,0xe7,0x23,0x8b,0xae,0xe4,0xe8,0xba,0x5d,0xcb,
+0x1e,0x89,0xe7,0x48,0x18,0x4f,0x40,0x7e,0x1f,0x1f,0x96,0x07,0xe4,0x9e,0xf7,0x7d,
+0x7d,0xeb,0x6f,0x82,0x7b,0xe2,0xf4,0x79,0xe0,0xdf,0x3f,0x4c,0x0f,0xd9,0xeb,0xef,
+0xfd,0x7f,0x7f,0x0f,0x37,0xab,0xf0,0xee,0x3f,0x4f,0xeb,0xe5,0x01,0xbe,0x90,0x2b,
+0xec,0xed,0xc0,0x0d,0xfb,0x9c,0xe7,0xb0,0xd0,0x53,0xa4,0xe0,0xba,0xae,0x3b,0xb2,
+0xec,0x38,0x8d,0xb4,0x1e,0xe6,0x41,0x90,0x6a,0xf7,0x0c,0x43,0x2e,0xa3,0x66,0xeb,
+0x42,0x90,0x93,0xb5,0x0e,0xb9,0x70,0xd4,0x36,0xb5,0x44,0xb0,0x5c,0x3e,0xeb,0xc4,
+0x70,0xab,0xad,0x15,0x37,0xd1,0x3c,0x50,0xc4,0x46,0x2d,0xbc,0x23,0x10,0x42,0x70,
+0xb4,0x73,0x12,0x46,0xcd,0x4c,0x69,0x20,0x37,0x80,0x7c,0x7c,0xb7,0x48,0x32,0x33,
+0x0d,0x21,0xc8,0x8b,0x24,0x8f,0x26,0x2d,0x52,0x4c,0x94,0xc6,0xc9,0xb2,0x92,0x7b,
+0x27,0xc9,0x52,0x9c,0xaf,0x2a,0xc8,0x92,0xbc,0xa7,0x2c,0xc7,0xd2,0xdc,0xa5,0x2e,
+0xc6,0xd2,0xfc,0x9b,0x30,0xc6,0x33,0x1c,0x99,0x32,0xc5,0x53,0x3c,0x8f,0x34,0xc4,
+0xb3,0x5c,0x8d,0x36,0xc3,0xb3,0x7c,0x83,0x38,0xc3,0x13,0x9c,0x81,0x3a,0xc1,0xf3,
+0xbc,0x69,0x3c,0xc1,0x53,0xba,0x0b,0x0d,0xcf,0xb0,0x04,0xf7,0x14,0x50,0x4f,0xc4,
+0xff,0x42,0xca,0x0e,0xf5,0x09,0x06,0xd0,0xcf,0x65,0x11,0x40,0xd1,0x52,0x8d,0x19,
+0x21,0x52,0x54,0x85,0x1b,0x4b,0x52,0x94,0xad,0x15,0x4b,0xb9,0xf4,0x73,0xf3,0x4d,
+0x34,0xb4,0xfb,0xbb,0x4e,0xd3,0x72,0x85,0x43,0x51,0x53,0x33,0x7d,0x01,0x4c,0x53,
+0x95,0x43,0x0f,0x51,0xc0,0x33,0x9d,0x59,0x4f,0x55,0x55,0x7a,0xf7,0x58,0xc2,0x15,
+0x9d,0x13,0x57,0x56,0xf5,0xc5,0x6d,0x5f,0x2d,0x35,0xcb,0xa3,0x60,0xd7,0xf5,0xed,
+0x8a,0xb4,0x58,0x70,0xcd,0x91,0x61,0x58,0x13,0x1d,0x69,0x53,0x4a,0xd6,0x65,0x93,
+0x67,0x4b,0xf6,0x85,0x53,0x63,0xda,0x68,0x1d,0x95,0x13,0x57,0x74,0x8d,0xb3,0x6d,
+0x5b,0x90,0x5d,0xb4,0xa4,0x5c,0x51,0x95,0xc9,0x2a,0x5a,0xb6,0x65,0xcc,0xdc,0x54,
+0xb6,0xc5,0x4f,0x6f,0x55,0xb7,0x85,0xd0,0x00,0x5d,0x91,0xbd,0xe9,0x7a,0xdd,0x56,
+0x45,0xed,0x1f,0xdf,0x17,0xe3,0x51,0x7c,0x5f,0x37,0x05,0xa7,0x7f,0xb4,0xf8,0x0e,
+0x0a,0xd0,0x60,0xf7,0xd5,0x8b,0x84,0x33,0xf8,0x56,0x07,0x75,0xe1,0x76,0x0e,0x1a,
+0xcf,0x61,0xf7,0x9d,0xd1,0x8a,0x37,0x37,0xf6,0x25,0x5f,0x63,0x2c,0x5e,0x2d,0x69,
+0x5e,0x98,0xf3,0x15,0x90,0x4b,0x58,0xde,0x21,0x7d,0xe3,0x95,0xbe,0x46,0xc4,0xe4,
+0xb2,0xf6,0x4f,0x8b,0xdc,0x99,0x63,0x81,0x98,0x64,0x38,0xc6,0x55,0x57,0xe6,0x6c,
+0x0e,0x5d,0x31,0x66,0xb9,0x36,0x45,0x9c,0x55,0x19,0xd3,0x01,0x9e,0x4c,0xd7,0x8d,
+0x6b,0x94,0x61,0x9a,0x0c,0x83,0x6b,0xb4,0x9a,0x1a,0xff,0xa2,0xcd,0x5a,0x3d,0xa3,
+0x9f,0xe6,0xfa,0x4c,0xa5,0xa6,0xd6,0x1a,0x5d,0x35,0xa7,0xaf,0xd7,0x76,0x9d,0xad,
+0xd2,0x9a,0xeb,0x9b,0xa9,0xdd,0xf9,0xb6,0x65,0xb0,0xc5,0x1a,0xcc,0x91,0xb4,0xd0,
+0x9b,0x1a,0xeb,0xaf,0xeb,0x5a,0xbe,0x3b,0xb6,0xc1,0xbb,0x5a,0xf9,0xb7,0xae,0x9a,
+0x8c,0xdd,0xb2,0xec,0x1b,0x9e,0x57,0xba,0xce,0xfb,0xcb,0x43,0x9f,0x65,0xfa,0x06,
+0xff,0x9c,0xf0,0x2d,0xe6,0xef,0x63,0x66,0x37,0x0f,0x14,0xd2,0xf1,0x8b,0x5f,0x06,
+0xb9,0x6f,0x73,0x96,0xfb,0xb9,0x71,0xd8,0x27,0x21,0x35,0xf2,0x8b,0x8f,0x2d,0x3b,
+0x70,0xb9,0xed,0x57,0x5e,0x73,0x52,0xdf,0x25,0x27,0x73,0x93,0x3f,0x3c,0xb8,0x74,
+0x13,0xd7,0x45,0xa3,0x70,0xfd,0x34,0xaf,0xd4,0x59,0xbc,0x44,0x8d,0xda,0xda,0x9d,
+0xbd,0x43,0xd6,0x2d,0xfd,0x74,0xfd,0xd8,0x6a,0x5d,0x96,0xcf,0x67,0xf4,0xbe,0x25,
+0xad,0xe3,0x6a,0xbb,0x47,0x77,0xae,0x75,0x53,0x1f,0x7b,0x22,0xf8,0x3b,0xe7,0x87,
+0xe5,0x71,0xfe,0x66,0xc5,0xe7,0x4b,0xfe,0x82,0xef,0xe9,0x72,0xfe,0xa7,0x0d,0xab,
+0x76,0x7a,0x57,0xaf,0x46,0x7b,0x72,0x5f,0xbb,0xd0,0xfb,0xfd,0x1f,0xc3,0xe3,0xe2,
+0x3f,0x26,0xdd,0xec,0xcb,0x7f,0x35,0x17,0xf5,0x76,0x3f,0x67,0xab,0xe4,0x5b,0xff,
+0x16,0x27,0xf8,0xcb,0x1f,0xea,0x00,0x00,0x81,0x40,0xe0,0x90,0x58,0x34,0x1c,0x00,
+0x0f,0x7f,0xc2,0xe1,0x90,0xd8,0x74,0x3e,0x21,0x11,0x89,0x44,0xdf,0xf0,0x88,0xb4,
+0x5e,0x30,0x20,0x8c,0x45,0xa1,0x51,0x48,0xf4,0x7e,0x41,0x0e,0x8d,0xc8,0xe4,0x92,
+0x58,0x2c,0x76,0x43,0x29,0x95,0x43,0xe4,0xd2,0xd8,0x2c,0x6a,0x5d,0x09,0x95,0xcc,
+0xe6,0x73,0x19,0xb4,0xda,0x51,0x34,0x9d,0x47,0xa6,0xf2,0xd9,0x84,0xba,0x73,0x3b,
+0xa1,0x44,0x27,0xb4,0x59,0x25,0x06,0x87,0x49,0x85,0xd1,0xa4,0x93,0xf9,0x6d,0x22,
+0x95,0x43,0xa6,0x54,0xe1,0x15,0x0a,0x8c,0xee,0xa9,0x19,0x9c,0x55,0xea,0xf5,0x9a,
+0xf4,0x0a,0xad,0x5c,0x9a,0xd7,0xe0,0xf4,0xe9,0x35,0x86,0xc5,0x2a,0xb2,0x56,0x6d,
+0x16,0x99,0x0d,0xae,0x0d,0x66,0x92,0xdb,0x6d,0xd1,0xfb,0x85,0x4e,0xe9,0x75,0x8a,
+0x5d,0xe0,0x97,0x2a,0x3d,0xea,0xb1,0x7c,0xa2,0xde,0x70,0x11,0x1c,0x16,0x0f,0x0b,
+0x34,0xc3,0xcf,0x70,0x98,0x99,0x16,0x2e,0xb7,0x8e,0xb5,0x64,0x26,0x38,0xdc,0x95,
+0x2f,0x0f,0x7e,0x91,0xe5,0xb2,0xf9,0x4c,0xae,0x5e,0x53,0x8b,0xcd,0x46,0xf3,0x99,
+0x2c,0xf5,0x03,0x41,0x6f,0xcc,0xe4,0x75,0x33,0xcd,0x3d,0x9f,0x5b,0x76,0xd7,0xdc,
+0xf6,0x3a,0xed,0x9e,0x6f,0x6b,0x7b,0xdb,0xee,0x37,0x31,0x2d,0x16,0xb3,0x7b,0x2c,
+0xd5,0xe7,0xf8,0x34,0x4d,0xde,0x93,0x8b,0xc6,0xe3,0xc5,0xf4,0xb8,0xee,0x5c,0x63,
+0x9b,0x89,0xe7,0xf3,0x39,0x3c,0x2e,0x9c,0x1f,0xa3,0x85,0xeb,0xd5,0x7a,0xb8,0xfe,
+0xdc,0x9f,0xbb,0x0d,0xef,0xc1,0xbb,0x38,0x0f,0x1f,0x83,0xc3,0x98,0xf3,0xd8,0x3d,
+0x3e,0xaf,0x5f,0x96,0xf5,0xeb,0x81,0xfc,0x2e,0xbf,0x2f,0x67,0xb7,0xed,0x32,0xfc,
+0x7d,0xbe,0x96,0xef,0xcf,0xf5,0x69,0x7f,0xde,0xd4,0x55,0xfc,0x80,0xe0,0x27,0xed,
+0xf2,0x80,0x16,0x28,0x1d,0xe9,0x83,0x1e,0x18,0x39,0xdd,0x84,0x1d,0x58,0x49,0xc9,
+0x85,0x1c,0x58,0x59,0xc1,0x86,0x1b,0xd8,0x69,0xb9,0x87,0x1b,0x58,0x79,0xb1,0x88,
+0x1a,0xd8,0x89,0xa9,0x6f,0xdc,0x48,0x36,0x05,0x82,0x17,0xc6,0x8d,0xd0,0x81,0xa2,
+0x98,0xa1,0x82,0x8b,0x1d,0x48,0xa9,0xe7,0x82,0x95,0xc8,0x99,0xa8,0x8d,0x1e,0x38,
+0xd9,0x5d,0x70,0xe3,0x98,0xc1,0xef,0x8b,0xa3,0x17,0x02,0x11,0x8b,0xe0,0xf8,0xf9,
+0x4f,0x90,0xa4,0x18,0xe9,0x6b,0x8c,0x91,0xc9,0x2a,0x35,0x94,0x17,0x09,0x39,0xdc,
+0x93,0x1d,0xb8,0xf1,0x51,0x8e,0x24,0x99,0x59,0xd7,0x96,0x14,0xa8,0x91,0xa0,0x98,
+0x19,0xd9,0x1a,0x45,0x82,0x65,0x29,0x36,0x44,0x84,0xe6,0x49,0xaa,0x43,0x89,0xe4,
+0x79,0x9a,0x5c,0x57,0xa5,0x47,0x62,0x67,0x95,0xe7,0x59,0x76,0x77,0x74,0xe5,0xe5,
+0x26,0x62,0x69,0xa4,0x86,0xc2,0x71,0x56,0x67,0x37,0x92,0x79,0x73,0xe7,0xb5,0x4a,
+0x6b,0x85,0x68,0x98,0x5e,0x8b,0x86,0x68,0xd8,0x6e,0x8f,0x87,0x69,0x18,0x7e,0x93,
+0x88,0x69,0x58,0x8e,0x97,0x89,0x69,0x99,0x86,0x9b,0x98,0xe7,0x09,0x02,0x51,0xa0,
+0x5c,0xba,0x1d,0x42,0x9f,0x5c,0xea,0x76,0x7e,0xa7,0xe6,0xf9,0x2e,0xa0,0x8e,0xe8,
+0x5a,0x8e,0xaf,0x71,0xea,0x46,0x06,0xaa,0x99,0x6a,0xca,0xae,0xa1,0xab,0x5d,0xfa,
+0xcd,0x3a,0xa9,0x9d,0x2a,0xa2,0xa7,0xad,0x66,0xca,0xde,0xb6,0xae,0x6b,0x8a,0xba,
+0xa2,0xac,0xab,0x15,0x32,0x83,0x7a,0x2b,0xa9,0xda,0xc9,0xb3,0x26,0x9a,0x2a,0xc2,
+0xb5,0x22,0xbb,0x4e,0x8c,0xb5,0x6d,0x9b,0x5e,0x6e,0xb1,0x6c,0x8b,0x3d,0x5f,0xb3,
+0x50,0x4a,0xf1,0x8a,0xb0,0x2b,0xf9,0xb6,0x3f,0xb1,0xeb,0xbb,0x2d,0x46,0xb8,0x9f,
+0x3b,0xb1,0xb3,0xb9,0x16,0x3b,0xa2,0x5b,0xb8,0x27,0xab,0xc1,0x3d,0xbb,0x9f,0x7b,
+0xda,0x86,0xbe,0x13,0x7b,0xe9,0xfa,0xbf,0x2b,0x0b,0x45,0xb7,0xbc,0x92,0xba,0xf9,
+0xda,0xb9,0xb0,0x9b,0x6a,0x8e,0xbd,0x28,0x0c,0x0a,0xca,0xc1,0x14,0x5c,0x03,0x06,
+0x64,0xf0,0xca,0x43,0x0e,0x6d,0x31,0x26,0xbf,0x15,0x68,0x70,0xa7,0x9b,0x1f,0x7c,
+0x72,0x17,0xd6,0x7f,0xc6,0xb1,0x0b,0x4a,0xdd,0xb0,0xec,0x6b,0x7a,0xeb,0xc6,0xda,
+0x7c,0x75,0xaa,0xc5,0xe9,0x2c,0xca,0x94,0xcd,0x29,0x6c,0xda,0x98,0xce,0x29,0xac,
+0xea,0x9c,0xcf,0x29,0xeb,0x13,0x2a,0xb7,0xee,0xab,0x43,0x27,0xc1,0x6f,0xe6,0x7b,
+0x30,0x48,0x30,0x8c,0x83,0x3e,0xaa,0x74,0x0b,0x5b,0x2b,0xd0,0x72,0xdd,0x16,0xf1,
+0xd1,0xd9,0x4d,0x25,0xb2,0xd3,0x6c,0x1d,0x3e,0xdb,0xd4,0x75,0x0d,0x0b,0x2c,0xd1,
+0x34,0x35,0x50,0x08,0x62,0x32,0xe4,0xb4,0x04,0xd9,0xb5,0x4c,0x73,0x56,0x64,0x35,
+0x86,0xdb,0x5c,0xc3,0x77,0x1c,0x62,0xdc,0xba,0x76,0x19,0xe3,0x67,0x4c,0x71,0x4d,
+0xb5,0x8b,0xdb,0xdb,0xac,0x65,0x7f,0xde,0x76,0xed,0xf1,0x26,0xde,0xf8,0x2d,0xf7,
+0x84,0x49,0x78,0x6d,0xaf,0x2f,0xe2,0x54,0xdb,0x63,0x72,0xd7,0xb5,0xd9,0x4f,0x90,
+0xdd,0x39,0x2e,0x47,0x94,0xca,0x75,0xfd,0x4f,0x63,0x9c,0xb9,0x5c,0xcf,0x73,0xe8,
+0x17,0x7e,0x2f,0x9d,0xbf,0x78,0x76,0x1f,0x7e,0x44,0xf4,0xbc,0x8b,0x5a,0xb9,0xfa,
+0x1c,0xd7,0x75,0xbd,0x7a,0x5c,0x0f,0x8c,0x4d,0xba,0x4d,0xde,0xf7,0xe9,0xf8,0xae,
+0x7f,0xb0,0xe5,0xf9,0x6d,0x83,0x52,0xd8,0xbb,0x8e,0x9b,0xb5,0xde,0xbb,0xcc,0xdf,
+0xaf,0xf2,0x3b,0xee,0x8b,0xc0,0xe6,0xfc,0x2f,0x07,0x78,0xf1,0x78,0x3e,0xe9,0x7c,
+0xea,0x5b,0xec,0x8d,0xfe,0xf6,0x20,0x1f,0x6a,0x0b,0xf7,0x23,0x7f,0x7a,0x3d,0xeb,
+0x70,0xbf,0x27,0x39,0xf9,0x33,0xbf,0x9b,0x3d,0xfa,0x33,0xff,0x2f,0xbd,0xf3,0x79,
+0x3e,0x73,0xc3,0xed,0x3b,0x3c,0x47,0xd2,0xe2,0x3d,0x45,0xdf,0xd6,0x61,0x97,0x70,
+0x08,0x40,0x63,0x38,0xe4,0x00,0x01,0x02,0x81,0xc1,0x20,0xb0,0x68,0x3c,0x18,0x1e,
+0xff,0x85,0xc3,0x21,0xb0,0xe8,0x7c,0x42,0x23,0x12,0x89,0xbf,0xe1,0x11,0x68,0xbc,
+0x5c,0x03,0x18,0x8b,0xc2,0xa2,0x91,0xe8,0xfc,0x82,0x1d,0x1b,0x91,0xc9,0x24,0xb0,
+0x58,0xec,0x86,0x53,0x2a,0x87,0xc9,0xa5,0xb2,0xe8,0x44,0xa2,0x57,0x32,0x94,0xcb,
+0xe5,0xd1,0xa9,0xac,0xc6,0x67,0x3a,0x8a,0x4d,0x67,0xb2,0xe9,0xcc,0xee,0x83,0x2c,
+0x9f,0x49,0x26,0xf2,0xfa,0x05,0x0a,0x93,0x15,0xa2,0x53,0x23,0x14,0x8a,0x55,0x06,
+0x9b,0x52,0x98,0x54,0x2a,0xb4,0xba,0x9c,0x18,0x89,0x02,0x10,0x4e,0x2a,0xd5,0x09,
+0x68,0x52,0xb1,0x23,0xa7,0xd7,0xa5,0x76,0x28,0xb5,0x72,0x8f,0x65,0xa4,0xd9,0xec,
+0x56,0x4b,0x5c,0x86,0xdb,0x07,0xb4,0xcf,0xee,0x15,0x1b,0x95,0x4a,0xdf,0x76,0x8f,
+0x5e,0x20,0xb7,0x49,0x6d,0xea,0xf7,0x13,0xbe,0xd3,0x70,0x38,0x28,0x8e,0x12,0x07,
+0x7f,0x93,0x61,0xb0,0xf4,0x3c,0x4c,0xf7,0x1b,0x8e,0x86,0xe1,0x04,0x95,0xba,0xee,
+0x4e,0x69,0x90,0xc8,0xe6,0x73,0x57,0xd2,0x00,0x03,0x17,0x25,0xc9,0x67,0x65,0xa0,
+0x24,0x04,0x98,0x05,0x44,0xd2,0x66,0x73,0x7a,0x29,0x26,0xb3,0x27,0x9b,0xce,0x67,
+0x64,0x1a,0xec,0xc6,0xd6,0xf9,0xb3,0xb5,0x6e,0x77,0x57,0x8b,0x4e,0xbe,0xc7,0xbd,
+0xdf,0x5c,0x80,0x9a,0xbe,0x1c,0xf3,0x77,0x75,0xe4,0x44,0xb9,0x5c,0xbe,0x64,0x43,
+0x9d,0x80,0xe8,0x62,0x3a,0x5a,0x3e,0xa7,0x46,0xfa,0x02,0xd0,0x70,0x63,0x7b,0x1c,
+0x77,0x5b,0xaf,0xd8,0x91,0x64,0x3b,0xb4,0xef,0x1f,0x93,0xc3,0xde,0xf4,0x65,0x3c,
+0xbb,0x8f,0x67,0xab,0x85,0xec,0x85,0xfc,0x7d,0x7f,0x3a,0xbf,0xd6,0xa9,0xf7,0xc4,
+0xe8,0x36,0x9f,0x3c,0x23,0x54,0xd0,0xbd,0xef,0x44,0x00,0xae,0x3c,0xc8,0xe3,0xee,
+0xfc,0x3f,0x28,0x4c,0x13,0x05,0xa2,0xce,0xfb,0x0f,0x07,0x3f,0x4f,0xfc,0x25,0x06,
+0x3f,0x69,0xa8,0x02,0xfe,0xa4,0x70,0x3c,0x1f,0x06,0xc2,0xa9,0x3c,0x3d,0x0f,0xa0,
+0x70,0x83,0x04,0x97,0x43,0x49,0x24,0x4e,0xe7,0xbe,0x0d,0x4b,0x4c,0xe3,0xc2,0xf1,
+0x12,0x05,0x12,0x2f,0x6b,0x03,0x95,0x19,0x2e,0xd1,0x84,0x47,0x10,0xc6,0x11,0xb2,
+0xe1,0x02,0xa7,0xd1,0xe2,0xd6,0xa2,0x0a,0x0c,0x24,0x80,0xb2,0xc7,0x11,0x8c,0x75,
+0x11,0x48,0xaa,0xf4,0x8e,0x00,0x49,0x6a,0xb4,0x9b,0x27,0xaa,0xb2,0x8c,0x93,0x0f,
+0xca,0x4a,0xfc,0x9b,0x2c,0xcb,0x52,0xdc,0xb9,0x2e,0xcb,0xd2,0xfc,0xc1,0x30,0xcc,
+0x53,0x1c,0xc9,0x32,0xa7,0xce,0x32,0x11,0x34,0x23,0x01,0x02,0x8d,0x33,0x24,0xb1,
+0x4a,0x06,0x08,0x23,0x70,0x0c,0xdd,0x3a,0xce,0xd3,0xbb,0xd5,0x0e,0x4f,0x09,0xf0,
+0x51,0x3d,0xbf,0x8c,0xbc,0xfc,0xb6,0xcd,0x54,0x0a,0x5d,0x41,0xcd,0x74,0x22,0x5b,
+0x39,0x51,0x0a,0xc0,0x1e,0xd4,0x24,0x80,0x44,0x05,0x45,0xa3,0x00,0x39,0x14,0x92,
+0xce,0x94,0x92,0xc5,0x3d,0x53,0x14,0xda,0x2c,0x50,0x30,0x94,0xd4,0xbb,0x36,0xa4,
+0xc0,0x95,0x38,0xb9,0xa4,0x80,0x15,0x40,0x82,0x55,0x35,0x2d,0x58,0xb4,0xc4,0xf3,
+0xea,0x0c,0x08,0xa5,0xf5,0x5c,0xbd,0x45,0x24,0x70,0xcd,0x58,0xbf,0x20,0xe0,0x3d,
+0x1c,0xa2,0x57,0x14,0xc5,0x79,0x5c,0xa4,0xad,0x78,0x1e,0x50,0xa5,0xd4,0xba,0x04,
+0xed,0xd2,0x4b,0x08,0x00,0x01,0x56,0xd3,0x7d,0x84,0x81,0x00,0x22,0x15,0x45,0x68,
+0xa4,0xb4,0x35,0xad,0x6c,0xdb,0x4f,0xcd,0x69,0x53,0xbb,0x96,0xdd,0xc1,0x6e,0xa4,
+0xa0,0x0d,0x7b,0x70,0x5b,0x36,0x42,0xa4,0xd0,0x5d,0x13,0xb5,0xca,0x8d,0x80,0x93,
+0x82,0x0d,0x6c,0x4e,0xd7,0x12,0x4b,0x76,0xdc,0xd5,0xcd,0xe9,0x7b,0xac,0x56,0x55,
+0xf4,0x8d,0xdc,0x96,0xb5,0x7e,0xa2,0xde,0x17,0xee,0x09,0x82,0xac,0xe2,0x26,0x07,
+0x7d,0x5f,0x80,0x02,0x6f,0x7c,0xe0,0xd8,0x7e,0x20,0x82,0xd9,0xe9,0xf0,0x0d,0x2f,
+0x56,0x10,0xc2,0x99,0x5e,0xd2,0x13,0x43,0x50,0xd0,0x63,0x68,0x16,0x3a,0x00,0x63,
+0xe0,0x06,0x43,0x91,0xe3,0x40,0x06,0x38,0x00,0x63,0xd9,0x42,0x6b,0x48,0x3a,0xd7,
+0x92,0x2f,0x98,0x3a,0x59,0x92,0x07,0x85,0xaa,0x4d,0x43,0x55,0x93,0x65,0x59,0x16,
+0x59,0x92,0x59,0xb9,0xe6,0x53,0x95,0xe8,0x3a,0x06,0x41,0x9d,0xa0,0x59,0xa4,0x61,
+0x97,0x52,0x58,0x0d,0x7c,0x81,0xd0,0x70,0xd6,0x9f,0xa7,0x20,0x9a,0x86,0x8b,0xaa,
+0x20,0x7a,0xb2,0xb1,0xa4,0x5b,0x20,0x2a,0x11,0x6a,0xe2,0x28,0xb5,0x51,0x83,0x66,
+0xcb,0x6e,0xb1,0xa3,0x67,0xa8,0x16,0xcb,0xb4,0xea,0x5a,0xbe,0xd7,0x4e,0x61,0x34,
+0x26,0xd5,0xa3,0xea,0x7b,0x6e,0xcd,0xa8,0xee,0x5b,0x66,0xef,0xaf,0xcc,0x9b,0x8e,
+0xcf,0xba,0xee,0x7b,0xce,0xfd,0xbc,0x6f,0xbb,0xd7,0x08,0x84,0x01,0x18,0x9a,0xdb,
+0x7b,0x62,0x3a,0xf4,0xc9,0xc3,0xaa,0x7b,0x7d,0xb3,0x8b,0xa0,0xb7,0x5c,0xfd,0xc7,
+0x70,0xb2,0xf6,0xc2,0x92,0xab,0x4b,0x97,0x2c,0x83,0xf2,0x0e,0x50,0x07,0x2d,0x71,
+0x88,0xb8,0x15,0x4c,0x73,0xa9,0xaf,0x3f,0x52,0xeb,0x88,0xde,0x1d,0x30,0x74,0xe9,
+0x1f,0x11,0xaf,0xe9,0x56,0x8f,0x5e,0x83,0xf2,0x98,0x8f,0x14,0x82,0xf3,0x74,0x97,
+0x6a,0x9e,0xb8,0x3d,0xcd,0xb7,0xca,0x74,0x7c,0xbf,0x89,0x6b,0x78,0x18,0x37,0x87,
+0xe2,0xf9,0x5c,0x27,0x67,0x4e,0x06,0x09,0x1d,0x98,0x83,0x75,0xbe,0x5f,0xa9,0x2f,
+0x79,0xeb,0xef,0x63,0x32,0xfa,0xeb,0xc7,0x9b,0x3c,0x7b,0x38,0x87,0xbf,0xea,0xfc,
+0x5f,0x1f,0xc9,0x4e,0x79,0x38,0x37,0x53,0x2d,0xf3,0x2f,0x0e,0xb5,0x82,0x7c,0x35,
+0xcf,0xb7,0xc2,0xfe,0x3e,0x27,0xdf,0x38,0xf8,0xbe,0xef,0xe1,0xb4,0x78,0xbf,0x6d,
+0xc1,0xfc,0x7c,0xa8,0x00,0x02,0x04,0x00,0x01,0x20,0x20,0x70,0x78,0x44,0x26,0x15,
+0x0b,0x86,0x40,0x82,0x30,0xd8,0x50,0x4a,0x21,0x13,0x86,0x02,0x22,0x91,0x78,0xc4,
+0x66,0x35,0x1b,0x8e,0x47,0x63,0xd1,0xf9,0x04,0x86,0x2b,0x22,0x92,0x49,0x64,0xd1,
+0x40,0x24,0x96,0x0b,0x27,0x96,0x48,0x22,0xd2,0xd9,0x84,0xc6,0x65,0x1a,0x11,0x4c,
+0xe6,0xd1,0x00,0x40,0x42,0x6f,0x3b,0x9e,0x43,0x40,0x24,0x08,0x18,0xa2,0x7b,0x43,
+0x8e,0x4e,0x68,0x94,0x7a,0x45,0x26,0x95,0x0d,0xa3,0x52,0xe9,0xd4,0xf8,0x10,0x52,
+0x06,0x18,0xa8,0x49,0xa9,0xb5,0x5a,0xc4,0x88,0xa1,0x4b,0x01,0x08,0x2a,0x15,0x7a,
+0xcd,0x86,0xc5,0x63,0x8a,0xce,0xac,0x90,0x70,0x65,0x9e,0xd5,0x5f,0xb3,0x5a,0xed,
+0xd6,0xfa,0x4d,0x82,0xe1,0x55,0x40,0xdc,0xe9,0x77,0x29,0x6c,0x1a,0xed,0x18,0xba,
+0xcb,0x40,0x37,0xb8,0x9d,0xe3,0x01,0x49,0xbe,0xe0,0xe8,0x78,0x2c,0x35,0x13,0x0b,
+0x89,0x9d,0xe2,0x31,0x93,0xcc,0x5e,0x3e,0x67,0x8e,0xc9,0x4d,0xb2,0x39,0x59,0x86,
+0x53,0x31,0x31,0xcb,0xe6,0xe4,0xf9,0xac,0xf4,0xb3,0x3b,0xa1,0x92,0x68,0x34,0x9a,
+0x7d,0x46,0xa7,0x55,0xab,0xd6,0x6b,0x6c,0x54,0x0d,0x74,0x92,0xff,0xad,0x01,0xec,
+0x64,0x23,0x0d,0xb6,0xe6,0xc5,0xb5,0x8f,0x80,0xb6,0x1a,0xcd,0xc0,0x03,0x79,0xba,
+0x8e,0x70,0x78,0x9c,0x7e,0x47,0x27,0x95,0xcb,0xe6,0x73,0x79,0xdc,0xfe,0x87,0x1f,
+0x87,0xd1,0x84,0xf0,0x7a,0x7d,0x48,0x3f,0x1b,0xb1,0xdb,0x8e,0xf5,0xfb,0x9d,0xae,
+0xe4,0x2a,0xf5,0xe1,0x00,0x4b,0xfc,0x90,0xbf,0x1f,0x87,0xcd,0xe7,0x84,0xfa,0x7b,
+0x9e,0xbf,0x64,0x1f,0xdd,0xdb,0xf8,0x7c,0x60,0x5a,0x3e,0x8e,0x9b,0xb1,0xf8,0xe8,
+0x7e,0xba,0x9f,0x84,0xfd,0xce,0x7f,0x9d,0x17,0xf1,0xcf,0x80,0xdd,0x08,0x16,0x02,
+0x5b,0x5f,0x67,0xdd,0xec,0x81,0xdc,0xf8,0x25,0xcd,0x83,0xdc,0xe8,0x45,0xcc,0x84,
+0xdc,0xd8,0x55,0xcb,0x85,0xdc,0xc8,0x65,0xca,0x86,0xd9,0xe7,0x79,0x14,0x87,0x5c,
+0x98,0x7d,0xca,0x88,0xdc,0x80,0x20,0x60,0x83,0x10,0x78,0x9d,0xc7,0x89,0x5b,0xa4,
+0xa6,0x0d,0x79,0xc0,0x28,0x2e,0x0c,0x8b,0x5c,0x48,0xbd,0xc8,0x8d,0xd8,0x90,0x05,
+0xf3,0x45,0x23,0x98,0xad,0x76,0x8f,0x55,0xc8,0xae,0x35,0x90,0x64,0x79,0x22,0x49,
+0x6a,0xe2,0x17,0x61,0xe0,0x92,0x9e,0x49,0x31,0xd4,0x75,0x9f,0x19,0x3a,0x4f,0x95,
+0xa5,0x79,0x62,0x59,0x96,0xa5,0xb9,0x72,0x5d,0x4b,0x65,0x17,0x46,0x53,0x7b,0x25,
+0x59,0x79,0xcb,0x98,0x1d,0x09,0x91,0xdb,0x57,0x90,0x28,0xf9,0xd4,0x12,0x24,0x99,
+0xb5,0xf9,0x9c,0x20,0xe9,0xcd,0xe7,0x7d,0x5f,0x68,0xed,0xb9,0x90,0x1c,0x49,0xe5,
+0xb9,0x91,0x9f,0x19,0xf5,0xb1,0x9e,0xdb,0xaa,0x05,0xae,0x1a,0x27,0xf7,0xb2,0x85,
+0x6b,0x68,0x36,0xe6,0x8a,0x6b,0x28,0xc6,0xda,0x8e,0x6a,0xe9,0x06,0xc6,0x92,0x6a,
+0x13,0x50,0x01,0x3a,0x10,0x00,0x28,0x30,0x20,0x21,0x11,0xca,0x61,0xb6,0x53,0x69,
+0xc8,0x30,0x88,0x83,0x96,0x6a,0x21,0x09,0x6c,0xdb,0xa6,0xf9,0x08,0x12,0x91,0x70,
+0x59,0x59,0x09,0x14,0x45,0x35,0x5b,0x99,0x62,0x4a,0xa5,0x0c,0xa9,0x1c,0xb1,0x45,
+0x18,0xae,0xe3,0x89,0x26,0x96,0x6a,0x69,0x46,0xba,0x71,0x7f,0x69,0xa8,0xac,0x20,
+0xb1,0x9d,0x08,0x2e,0x6b,0x7d,0xab,0xfa,0xdd,0xf6,0xa8,0x5c,0x70,0x11,0xbf,0xb4,
+0x5e,0xa8,0xae,0x77,0x74,0xa5,0x4b,0x5d,0xce,0x99,0xdc,0xf9,0x89,0x2c,0xb6,0x98,
+0xc9,0xa5,0xa5,0xb7,0x6e,0x7b,0xa2,0xe9,0xba,0xae,0xbb,0xb1,0x4a,0xb4,0xe5,0x0b,
+0x71,0xc2,0xbc,0x51,0x89,0x0e,0xed,0x63,0xed,0xf7,0x39,0xb8,0xb5,0x92,0x7a,0xad,
+0x43,0xbf,0x53,0x0b,0x29,0x17,0x4a,0xef,0x45,0x22,0xd0,0x55,0x90,0x2c,0x19,0xe4,
+0x01,0x2c,0xb4,0x7d,0x0f,0x66,0xee,0x37,0x9f,0x0c,0x47,0x55,0x26,0x7b,0x10,0x42,
+0xf1,0x66,0x1a,0xb9,0x43,0x31,0x27,0x95,0xa7,0x8c,0x63,0xf9,0x26,0xff,0x7d,0x31,
+0xa7,0x72,0xc2,0x6a,0x2c,0x46,0xb0,0x60,0xc9,0x94,0xac,0x0d,0x2d,0xb2,0x29,0xdc,
+0xad,0xa4,0xca,0x1a,0xcc,0x89,0xd8,0xcc,0xda,0xbc,0xd5,0xd4,0xcd,0xda,0xac,0xe5,
+0xf9,0xc9,0x1d,0xbc,0xc5,0xa1,0x51,0x8f,0xfd,0x10,0xff,0x3c,0x00,0x03,0x00,0x80,
+0x45,0x80,0xc0,0x20,0x30,0x28,0x34,0x82,0x01,0x3a,0x4b,0xd5,0xed,0x25,0x02,0xd3,
+0x10,0x3d,0x55,0x21,0xd6,0x75,0x74,0x0b,0x5b,0x79,0x8c,0x02,0x21,0x29,0xd7,0x35,
+0x0d,0x5b,0x5f,0x5e,0xb6,0x3d,0x78,0x00,0x03,0xf4,0x40,0x03,0x45,0xd1,0x90,0x3b,
+0x39,0x5d,0x40,0xd6,0x66,0xe2,0xce,0x56,0x40,0x8c,0xf5,0x1f,0xda,0xcf,0xfd,0xb7,
+0x45,0xd1,0xf5,0x90,0x22,0xce,0xda,0x75,0xdd,0x9f,0x66,0x48,0xb8,0x3d,0x90,0x00,
+0xd8,0xc8,0x34,0x0f,0x68,0xe1,0x75,0x8e,0x3f,0x84,0xd9,0x76,0xad,0xb3,0x6e,0xd1,
+0xd0,0x8c,0xfd,0xae,0xde,0xf7,0xdd,0x13,0x7f,0xe4,0x78,0x90,0x21,0xbf,0xe2,0x35,
+0x94,0x83,0xa3,0xe7,0xf5,0xb4,0x1c,0xc0,0xe3,0x78,0x6e,0x2b,0xac,0xd5,0xf9,0xbe,
+0x59,0x18,0xe6,0x59,0xee,0xc3,0x7e,0xe8,0x3a,0x9d,0x9f,0xb8,0xe4,0xf9,0x2d,0x6b,
+0xa7,0xe7,0xe9,0xfe,0xef,0x89,0xe3,0xbc,0x1d,0xa7,0xb5,0xe7,0x50,0x9a,0xd9,0x73,
+0xde,0x52,0x0f,0x18,0xff,0x3c,0xdd,0x94,0x0d,0xd3,0x71,0xbd,0x2f,0x45,0x24,0xf5,
+0x10,0x2f,0x5e,0xf2,0x40,0xfd,0x3f,0x43,0xd8,0xf7,0x7d,0xa4,0x09,0xc6,0xf3,0x7c,
+0xff,0x6f,0xd5,0xf9,0x7d,0xef,0x9f,0xe0,0x48,0x3d,0x9f,0xb3,0xdf,0xfb,0x7e,0x9f,
+0x67,0xe3,0xfb,0xbf,0x3f,0xc3,0xd6,0xfd,0x3e,0x1f,0x9b,0xf8,0xfa,0x3f,0xaf,0xab,
+0xdc,0xfa,0x50,0x00,0x7b,0xfd,0xfe,0x00,0x81,0xc0,0xde,0x60,0x08,0x48,0x00,0x61,
+0x0a,0x01,0xc2,0xa1,0x70,0xd8,0x7c,0x32,0x13,0x0e,0x87,0xc5,0xa2,0xf1,0x88,0x8c,
+0x2a,0x26,0x00,0x8a,0xc2,0x63,0x91,0xe8,0x84,0x52,0x25,0x1a,0x8f,0xc9,0x64,0x40,
+0x08,0x14,0x12,0x0c,0xff,0x78,0x00,0x18,0x10,0xa0,0x41,0x42,0x14,0xc0,0x40,0x42,
+0x41,0x80,0x89,0xa4,0xd8,0x01,0x38,0x9d,0x46,0x67,0xf1,0x99,0xac,0xde,0x73,0x09,
+0xa1,0x4f,0x28,0x92,0xf9,0xdc,0xf6,0x8b,0x0a,0xa5,0xd2,0x68,0x73,0xea,0x3c,0xa6,
+0x07,0x05,0x83,0x4b,0xa8,0x15,0x8a,0xcd,0x6a,0xb7,0x5c,0xae,0xd7,0x25,0x55,0x58,
+0x1c,0xb9,0x05,0x4d,0xa4,0x59,0x2a,0x14,0x5a,0x55,0x22,0x8d,0x5e,0x8b,0xd1,0xa9,
+0xd6,0xfb,0x5d,0xaa,0xa3,0x70,0xb9,0xda,0x6a,0x16,0x09,0x64,0xb8,0x03,0x19,0xbe,
+0x5b,0x6f,0xf8,0x0c,0x0d,0x7a,0xf3,0x56,0xa7,0x80,0x01,0x04,0x0b,0xa5,0xca,0xd1,
+0x86,0xc1,0x61,0xae,0xb8,0xcb,0x8e,0x2b,0x27,0x77,0xa9,0x61,0x2c,0x51,0x70,0x86,
+0x3b,0x37,0x9c,0xce,0xc2,0x72,0xf2,0xd0,0x04,0xdb,0x35,0x3d,0x10,0x00,0x10,0x37,
+0xe9,0xc5,0xfb,0x25,0x95,0xc7,0x6b,0x31,0xf8,0xba,0x96,0x57,0x21,0xb2,0xd8,0x54,
+0xe5,0x78,0x58,0x75,0x20,0x01,0x89,0x02,0x00,0xa2,0xd3,0xbc,0xf7,0x0b,0x87,0x0a,
+0xd0,0x55,0xf8,0x9c,0x8e,0x4d,0x67,0x8d,0xca,0xe6,0xf3,0xa2,0xd6,0x01,0x50,0x01,
+0xf9,0xbf,0x94,0xa3,0xc1,0xa5,0xb3,0x49,0xfc,

+ 2 - 0
logic/boot.post.asf

@@ -0,0 +1,2 @@
+# pio_begin  >>>>>> DO NOT MODIFY THIS SECTION! >>>>>>
+# pio_end    <<<<<< DO NOT MODIFY THIS SECTION! <<<<<<

+ 6 - 0
logic/boot.pre.asf

@@ -0,0 +1,6 @@
+# pio_begin  >>>>>> DO NOT MODIFY THIS SECTION! >>>>>>
+set BOARD_PLL_CLKIN PIN_HSE
+set db_io_name_priority true
+set ip_pll_vco_lowpower true
+set_global_assignment -name ON_CHIP_BITSTREAM_DECOMPRESSION "ON"
+# pio_end    <<<<<< DO NOT MODIFY THIS SECTION! <<<<<<

+ 40 - 0
logic/boot.proj

@@ -0,0 +1,40 @@
+[GuiMigrateSetupPage]
+design=boot
+device=AGRV2KL100
+
+[GuiMigrateRunPage]
+fitting=1
+fitter=5
+effort=2
+skew=2
+isMC=false
+count=
+jobs=
+seed=
+retry=0
+holdx=0
+skope=0
+preset=0
+adjust=0
+target=0
+tuning=0
+corner=0
+flow=0
+orgPlace=false
+quartusSdc=true
+probeForce=false
+probeState=@ByteArray(\0\0\0\xff\0\0\0\0\0\0\0\x1\0\0\0\x1\0\0\0\x2\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x2i\0\0\0\x2\0\x1\x1\x1\0\0\0\0\0\0\0\0\0\0\0\0\x64\0\0\0K\0\0\0\x4\0\0\0\0\0\0\0\x2\0\0\x1\xc2\0\0\0\x1\0\0\0\0\0\0\0\xa7\0\0\0\x1\0\0\0\0)
+probeCount=5
+probe0From=
+probe0Pad=
+probe1From=
+probe1Pad=
+probe2From=
+probe2Pad=
+probe3From=
+probe3Pad=
+probe4From=
+probe4Pad=
+
+[MainWindow]
+recentFile.0=

+ 3 - 0
logic/boot.qpf

@@ -0,0 +1,3 @@
+#QUARTUS_VERSION = "11.1"
+PROJECT_REVISION = "boot"
+

+ 141 - 0
logic/boot.qsf

@@ -0,0 +1,141 @@
+# Design name Assignments, replace __design_name__ with actual design name
+# ========================
+set_global_assignment -name FAMILY "Cyclone IV E"
+set_global_assignment -name DEVICE EP4CE75F29C8
+
+set_global_assignment -name TOP_LEVEL_ENTITY "top"
+
+set_global_assignment -name VERILOG_FILE boot.v
+set_global_assignment -name VERILOG_FILE boot_ip.v
+set_global_assignment -name VERILOG_FILE "C:\\Users\\61552\\.platformio\\packages\\tool-agrv_logic\\etc\\arch\\rodinia\\alta_sim.v"
+
+set_global_assignment -name SDC_FILE .\\boot.sdc
+
+
+#set_global_assignment -name LOGICLOCK_INCREMENTAL_COMPILE_FILE "atom_netlists/__design_name__.vqm"
+
+# Project-Wide Assignments
+# ========================
+set_global_assignment -name ORIGINAL_QUARTUS_VERSION 11.1
+set_global_assignment -name PROJECT_CREATION_TIME_DATE "09:37:04  JANUARY 04, 2013"
+set_global_assignment -name LAST_QUARTUS_VERSION 15.0.0
+set_global_assignment -name PROJECT_OUTPUT_DIRECTORY ./quartus_logs
+set_global_assignment -name NUM_PARALLEL_PROCESSORS ALL
+set_global_assignment -name FLOW_ENABLE_IO_ASSIGNMENT_ANALYSIS ON
+#set_global_assignment -name SMART_RECOMPILE ON
+
+# Classic Timing Assignments
+# ==========================
+set_global_assignment -name MIN_CORE_JUNCTION_TEMP 0
+set_global_assignment -name MAX_CORE_JUNCTION_TEMP 85
+
+# Analysis & Synthesis Assignments
+# ================================
+set_global_assignment -name SYNTH_TIMING_DRIVEN_SYNTHESIS ON
+set_global_assignment -name ADV_NETLIST_OPT_SYNTH_WYSIWYG_REMAP ON
+#set_global_assignment -name MAX_BALANCING_DSP_BLOCKS 0
+#set_global_assignment -name AUTO_ROM_RECOGNITION OFF
+#set_global_assignment -name AUTO_RAM_RECOGNITION OFF
+#set_global_assignment -name MAX_RAM_BLOCKS_M4K 0
+set_global_assignment -name AUTO_OPEN_DRAIN_PINS OFF
+# set_instance_assignment -name PRESERVE_REGISTER ON -to *
+#set_instance_assignment -name PRESERVE_PLL_COUNTER_ORDER ON -to *
+#set_instance_assignment -name MAX_NUMBER_OF_REGISTERS_FROM_UNINFERRED_RAMS 0 -to *
+
+# Fitter Assignments
+# ==================
+set_global_assignment -name ERROR_CHECK_FREQUENCY_DIVISOR 1
+set_global_assignment -name ROUTING_BACK_ANNOTATION_MODE OFF
+set_global_assignment -name OPTIMIZE_HOLD_TIMING "IO PATHS AND MINIMUM TPD PATHS"
+set_global_assignment -name FITTER_EFFORT "STANDARD FIT"
+set_global_assignment -name ROUTER_TIMING_OPTIMIZATION_LEVEL MAXIMUM
+set_global_assignment -name PLACEMENT_EFFORT_MULTIPLIER 10
+set_global_assignment -name ROUTER_EFFORT_MULTIPLIER 10
+set_global_assignment -name ECO_OPTIMIZE_TIMING ON
+set_global_assignment -name FINAL_PLACEMENT_OPTIMIZATION ALWAYS
+set_global_assignment -name FITTER_AGGRESSIVE_ROUTABILITY_OPTIMIZATION ALWAYS
+set_global_assignment -name STRATIX_DEVICE_IO_STANDARD "3.3-V LVTTL"
+set_global_assignment -name IO_PLACEMENT_OPTIMIZATION ON
+set_global_assignment -name SEED 1
+set_global_assignment -name FIT_ONLY_ONE_ATTEMPT OFF
+set_global_assignment -name MAX_GLOBAL_CLOCKS_ALLOWED 6
+set_global_assignment -name PHYSICAL_SYNTHESIS_COMBO_LOGIC ON
+#set_global_assignment -name PHYSICAL_SYNTHESIS_REGISTER_RETIMING ON
+#set_global_assignment -name PHYSICAL_SYNTHESIS_REGISTER_DUPLICATION ON
+set_global_assignment -name PHYSICAL_SYNTHESIS_COMBO_LOGIC_FOR_AREA ON
+set_global_assignment -name PHYSICAL_SYNTHESIS_EFFORT EXTRA
+
+# EDA Netlist Writer Assignments
+# ==============================
+set_global_assignment -name EDA_SIMULATION_TOOL "ModelSim (Verilog)"
+
+# LogicLock Region Assignments
+# ============================
+set_global_assignment -name LOGICLOCK_INCREMENTAL_COMPILE_ASSIGNMENT OFF
+
+# Power Estimation Assignments
+# ============================
+set_global_assignment -name POWER_PRESET_COOLING_SOLUTION "23 MM HEAT SINK WITH 200 LFPM AIRFLOW"
+set_global_assignment -name POWER_BOARD_THERMAL_MODEL "NONE (CONSERVATIVE)"
+
+# start EDA_TOOL_SETTINGS(eda_simulation)
+# ---------------------------------------
+
+# EDA Netlist Writer Assignments
+# ==============================
+set_global_assignment -name EDA_TIME_SCALE "1 ps" -section_id eda_simulation
+set_global_assignment -name EDA_OUTPUT_DATA_FORMAT "VERILOG HDL" -section_id eda_simulation
+
+# end EDA_TOOL_SETTINGS(eda_simulation)
+# -------------------------------------
+
+# start DESIGN_PARTITION(Top)
+# ---------------------------
+
+# Incremental Compilation Assignments
+# ===================================
+set_global_assignment -name PARTITION_NETLIST_TYPE SOURCE -section_id Top
+set_global_assignment -name PARTITION_FITTER_PRESERVATION_LEVEL PLACEMENT_AND_ROUTING -section_id Top
+set_global_assignment -name PARTITION_COLOR 16764057 -section_id Top
+set_global_assignment -name FLOW_DISABLE_ASSEMBLER ON
+
+# end DESIGN_PARTITION(Top)
+# -------------------------
+
+set_global_assignment -name LL_ENABLED ON -section_id core_logic
+set_global_assignment -name LL_AUTO_SIZE OFF -section_id core_logic
+set_global_assignment -name LL_STATE LOCKED -section_id core_logic
+set_global_assignment -name LL_RESERVED OFF -section_id core_logic
+set_global_assignment -name LL_SECURITY_ROUTING_INTERFACE OFF -section_id core_logic
+set_global_assignment -name LL_IGNORE_IO_BANK_SECURITY_CONSTRAINT OFF -section_id core_logic
+set_global_assignment -name LL_PR_REGION OFF -section_id core_logic
+set_global_assignment -name LL_WIDTH 20 -section_id core_logic
+set_global_assignment -name LL_HEIGHT 12 -section_id core_logic
+set_global_assignment -name LL_ORIGIN X43_Y1 -section_id core_logic
+set_global_assignment -name LL_MEMBER_OF core_logic -section_id core_logic
+
+set_global_assignment -name LL_ENABLED ON -section_id LOGIC_RESERVE_0
+set_global_assignment -name LL_AUTO_SIZE OFF -section_id LOGIC_RESERVE_0
+set_global_assignment -name LL_STATE LOCKED -section_id LOGIC_RESERVE_0
+set_global_assignment -name LL_RESERVED ON -section_id LOGIC_RESERVE_0
+set_global_assignment -name LL_SECURITY_ROUTING_INTERFACE OFF -section_id LOGIC_RESERVE_0
+set_global_assignment -name LL_IGNORE_IO_BANK_SECURITY_CONSTRAINT OFF -section_id LOGIC_RESERVE_0
+set_global_assignment -name LL_PR_REGION OFF -section_id LOGIC_RESERVE_0
+set_global_assignment -name LL_WIDTH 13 -section_id LOGIC_RESERVE_0
+set_global_assignment -name LL_HEIGHT 8 -section_id LOGIC_RESERVE_0
+set_global_assignment -name LL_ORIGIN X43_Y5 -section_id LOGIC_RESERVE_0
+
+set_global_assignment -name MAX_BALANCING_DSP_BLOCKS 0
+set_global_assignment -name MAX_RAM_BLOCKS_M4K 4
+
+
+set_global_assignment -name PARTITION_COLOR 52377 -section_id rv32 -tag alta_auto
+set_global_assignment -name PARTITION_NETLIST_TYPE SOURCE -section_id rv32 -tag alta_auto
+set_global_assignment -name PARTITION_FITTER_PRESERVATION_LEVEL PLACEMENT_AND_ROUTING -section_id rv32 -tag alta_auto
+set_global_assignment -name EDA_MAINTAIN_DESIGN_HIERARCHY PARTITION_ONLY -section_id eda_simulation
+set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top
+set_instance_assignment -name PARTITION_HIERARCHY rv32 -to "alta_rv32:rv32" -section_id rv32
+set_global_assignment -name LL_CORE_ONLY OFF -section_id LOGIC_RESERVE_0
+set_global_assignment -name LL_ROUTING_REGION_EXPANSION_SIZE 2147483647 -section_id LOGIC_RESERVE_0
+set_global_assignment -name LL_CORE_ONLY OFF -section_id core_logic
+set_global_assignment -name LL_ROUTING_REGION_EXPANSION_SIZE 2147483647 -section_id core_logic

BIN
logic/boot.qws


+ 13 - 0
logic/boot.sdc

@@ -0,0 +1,13 @@
+# pio_begin
+if { ! [info exists ::HSI_PERIOD] } {
+  set ::HSI_PERIOD 100.0
+}
+create_clock -name PIN_HSI -period $::HSI_PERIOD [get_ports PIN_HSI]
+set_clock_groups -asynchronous -group PIN_HSI
+if { ! [info exists ::HSE_PERIOD] } {
+  set ::HSE_PERIOD 125.0
+}
+create_clock -name PIN_HSE -period $::HSE_PERIOD [get_ports PIN_HSE]
+set_clock_groups -asynchronous -group PIN_HSE
+derive_pll_clocks -create_base_clocks
+# pio_end

+ 362 - 0
logic/boot.v

@@ -0,0 +1,362 @@
+`timescale 1 ps/ 1 ps
+
+module top (
+  PIN_1,
+  PIN_2,
+  PIN_3,
+  PIN_68,
+  PIN_69,
+  PIN_88,
+  PIN_91,
+  PIN_92,
+  PIN_95,
+  PIN_96,
+  PIN_97,
+  PIN_HSE,
+  PIN_HSI,
+  PIN_OSC
+);
+inout PIN_1;
+inout PIN_2;
+inout PIN_3;
+output PIN_68;
+input PIN_69;
+inout PIN_88;
+inout PIN_91;
+inout PIN_92;
+inout PIN_95;
+inout PIN_96;
+inout PIN_97;
+input PIN_HSE;
+input PIN_HSI;
+input PIN_OSC;
+
+// GPIO1_3, GPIO1_3
+assign PIN_1_in = PIN_1;
+wire PIN_1_out_en;
+wire PIN_1_out_data;
+assign PIN_1 = PIN_1_out_en ? PIN_1_out_data : 1'bz;
+
+// GPIO1_0, GPIO1_0
+assign PIN_2_in = PIN_2;
+wire PIN_2_out_en;
+wire PIN_2_out_data;
+assign PIN_2 = PIN_2_out_en ? PIN_2_out_data : 1'bz;
+
+// GPIO1_1, GPIO1_1
+assign PIN_3_in = PIN_3;
+wire PIN_3_out_en;
+wire PIN_3_out_data;
+assign PIN_3 = PIN_3_out_en ? PIN_3_out_data : 1'bz;
+
+// UART0_UARTTXD, GPIO7_6
+wire PIN_68_out_en;
+wire PIN_68_out_data;
+assign PIN_68 = PIN_68_out_en ? PIN_68_out_data : 1'bz;
+
+// UART0_UARTRXD, GPIO6_1
+assign PIN_69_in = PIN_69;
+
+// GPIO1_6, GPIO1_6
+assign PIN_88_in = PIN_88;
+wire PIN_88_out_en;
+wire PIN_88_out_data;
+assign PIN_88 = PIN_88_out_en ? PIN_88_out_data : 1'bz;
+
+// GPIO1_5, GPIO1_5
+assign PIN_91_in = PIN_91;
+wire PIN_91_out_en;
+wire PIN_91_out_data;
+assign PIN_91 = PIN_91_out_en ? PIN_91_out_data : 1'bz;
+
+// GPIO1_4, GPIO1_4
+assign PIN_92_in = PIN_92;
+wire PIN_92_out_en;
+wire PIN_92_out_data;
+assign PIN_92 = PIN_92_out_en ? PIN_92_out_data : 1'bz;
+
+// GPIO2_1, GPIO2_1
+assign PIN_95_in = PIN_95;
+wire PIN_95_out_en;
+wire PIN_95_out_data;
+assign PIN_95 = PIN_95_out_en ? PIN_95_out_data : 1'bz;
+
+// GPIO2_2, GPIO2_2
+assign PIN_96_in = PIN_96;
+wire PIN_96_out_en;
+wire PIN_96_out_data;
+assign PIN_96 = PIN_96_out_en ? PIN_96_out_data : 1'bz;
+
+// GPIO2_0, GPIO2_0
+assign PIN_97_in = PIN_97;
+wire PIN_97_out_en;
+wire PIN_97_out_data;
+assign PIN_97 = PIN_97_out_en ? PIN_97_out_data : 1'bz;
+
+// HSE clock
+assign PIN_HSE_in = PIN_HSE;
+
+// HSI clock
+assign PIN_HSI_in = PIN_HSI;
+
+// OSC clock
+assign PIN_OSC_in = PIN_OSC;
+
+wire [4:0] PLL_CLKOUT;
+(* keep = 1 *) wire       sys_resetn;
+(* keep = 1 *) wire       sys_ctrl_stop;
+(* keep = 1 *) wire [1:0] sys_ctrl_clkSource;
+(* keep = 1 *) wire       PLL_ENABLE;
+(* keep = 1 *) wire       PLL_LOCK;
+
+altpll pll_inst (
+  .areset(!PLL_ENABLE),
+  .inclk (PIN_HSE_in),
+  .clk   (PLL_CLKOUT),
+  .locked(PLL_LOCK));
+defparam pll_inst.bandwidth_type          = "AUTO";
+defparam pll_inst.clk0_divide_by          = 6;
+defparam pll_inst.clk0_multiply_by        = 90;
+defparam pll_inst.clk0_phase_shift        = "0";
+defparam pll_inst.clk1_divide_by          = 6;
+defparam pll_inst.clk1_multiply_by        = 90;
+defparam pll_inst.clk1_phase_shift        = "0";
+defparam pll_inst.clk2_divide_by          = 6;
+defparam pll_inst.clk2_multiply_by        = 90;
+defparam pll_inst.clk2_phase_shift        = "0";
+defparam pll_inst.clk3_divide_by          = 6;
+defparam pll_inst.clk3_multiply_by        = 90;
+defparam pll_inst.clk3_phase_shift        = "0";
+defparam pll_inst.clk4_divide_by          = 6;
+defparam pll_inst.clk4_multiply_by        = 90;
+defparam pll_inst.clk4_phase_shift        = "0";
+defparam pll_inst.compensate_clock        = "CLK0";
+defparam pll_inst.inclk0_input_frequency  = 125000;
+defparam pll_inst.lpm_type                = "altpll";
+defparam pll_inst.operation_mode          = "NORMAL";
+defparam pll_inst.pll_type                = "AUTO";
+defparam pll_inst.port_areset             = "PORT_USED";
+defparam pll_inst.port_inclk0             = "PORT_USED";
+defparam pll_inst.port_locked             = "PORT_USED";
+defparam pll_inst.port_clk0               = "PORT_USED";
+defparam pll_inst.port_clk1               = "PORT_UNUSED";
+defparam pll_inst.port_clk2               = "PORT_UNUSED";
+defparam pll_inst.port_clk3               = "PORT_UNUSED";
+defparam pll_inst.port_clk4               = "PORT_UNUSED";
+defparam pll_inst.width_clock             = 5;
+
+wire sys_gck;
+assign bus_clk = sys_gck;
+
+// Location: BBOX_X22_Y4_N0 FIXED_COORD
+alta_gclksw gclksw_inst (
+    .resetn(sys_resetn),
+    .ena   (1'b1),
+    .clkin0(PIN_HSI_in),
+    .clkin1(PIN_HSE_in),
+    .clkin2(PLL_CLKOUT[0]),
+    .clkin3(),
+    .select(sys_ctrl_clkSource),
+    .clkout(sys_clk));
+assign sys_gck = sys_clk;
+
+(* keep = 1 *) wire [1:0]  mem_ahb_htrans;
+(* keep = 1 *) wire        mem_ahb_hready;
+(* keep = 1 *) wire        mem_ahb_hwrite;
+(* keep = 1 *) wire [31:0] mem_ahb_haddr;
+(* keep = 1 *) wire [2:0]  mem_ahb_hsize;
+(* keep = 1 *) wire [2:0]  mem_ahb_hburst;
+(* keep = 1 *) wire [31:0] mem_ahb_hwdata;
+(* keep = 1 *) wire        mem_ahb_hreadyout;
+(* keep = 1 *) wire        mem_ahb_hresp;
+(* keep = 1 *) wire [31:0] mem_ahb_hrdata;
+
+(* keep = 1 *) wire        slave_ahb_hsel;
+(* keep = 1 *) wire        slave_ahb_hready;
+(* keep = 1 *) wire        slave_ahb_hreadyout;
+(* keep = 1 *) wire [1:0]  slave_ahb_htrans;
+(* keep = 1 *) wire [2:0]  slave_ahb_hsize;
+(* keep = 1 *) wire [2:0]  slave_ahb_hburst;
+(* keep = 1 *) wire        slave_ahb_hwrite;
+(* keep = 1 *) wire [31:0] slave_ahb_haddr;
+(* keep = 1 *) wire [31:0] slave_ahb_hwdata;
+(* keep = 1 *) wire        slave_ahb_hresp;
+(* keep = 1 *) wire [31:0] slave_ahb_hrdata;
+
+(* keep = 1 *) wire [3:0]  ext_dma_DMACBREQ;
+(* keep = 1 *) wire [3:0]  ext_dma_DMACLBREQ;
+(* keep = 1 *) wire [3:0]  ext_dma_DMACSREQ;
+(* keep = 1 *) wire [3:0]  ext_dma_DMACLSREQ;
+(* keep = 1 *) wire [3:0]  ext_dma_DMACCLR;
+(* keep = 1 *) wire [3:0]  ext_dma_DMACTC;
+(* keep = 1 *) wire [3:0]  local_int;
+
+boot_ip macro_inst(
+  .sys_clock          (sys_gck            ),
+  .bus_clock          (bus_clk            ),
+  .resetn             (sys_resetn         ),
+  .stop               (sys_ctrl_stop      ),
+  .mem_ahb_htrans     (mem_ahb_htrans     ),
+  .mem_ahb_hready     (mem_ahb_hready     ),
+  .mem_ahb_hwrite     (mem_ahb_hwrite     ),
+  .mem_ahb_haddr      (mem_ahb_haddr      ),
+  .mem_ahb_hsize      (mem_ahb_hsize      ),
+  .mem_ahb_hburst     (mem_ahb_hburst     ),
+  .mem_ahb_hwdata     (mem_ahb_hwdata     ),
+  .mem_ahb_hreadyout  (mem_ahb_hreadyout  ),
+  .mem_ahb_hresp      (mem_ahb_hresp      ),
+  .mem_ahb_hrdata     (mem_ahb_hrdata     ),
+  .slave_ahb_hsel     (slave_ahb_hsel     ),
+  .slave_ahb_hready   (slave_ahb_hready   ),
+  .slave_ahb_hreadyout(slave_ahb_hreadyout),
+  .slave_ahb_htrans   (slave_ahb_htrans   ),
+  .slave_ahb_hsize    (slave_ahb_hsize    ),
+  .slave_ahb_hburst   (slave_ahb_hburst   ),
+  .slave_ahb_hwrite   (slave_ahb_hwrite   ),
+  .slave_ahb_haddr    (slave_ahb_haddr    ),
+  .slave_ahb_hwdata   (slave_ahb_hwdata   ),
+  .slave_ahb_hresp    (slave_ahb_hresp    ),
+  .slave_ahb_hrdata   (slave_ahb_hrdata   ),
+  .ext_dma_DMACBREQ   (ext_dma_DMACBREQ   ),
+  .ext_dma_DMACLBREQ  (ext_dma_DMACLBREQ  ),
+  .ext_dma_DMACSREQ   (ext_dma_DMACSREQ   ),
+  .ext_dma_DMACLSREQ  (ext_dma_DMACLSREQ  ),
+  .ext_dma_DMACCLR    (ext_dma_DMACCLR    ),
+  .ext_dma_DMACTC     (ext_dma_DMACTC     ),
+  .local_int          (local_int          )
+);
+
+(* keep = 1 *) wire [7:0] gpio0_io_out_data;
+(* keep = 1 *) wire [7:0] gpio0_io_out_en;
+(* keep = 1 *) wire [7:0] gpio0_io_in = {1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0};
+
+(* keep = 1 *) wire [7:0] gpio1_io_out_data;
+(* keep = 1 *) wire [7:0] gpio1_io_out_en;
+assign PIN_2_out_data = gpio1_io_out_data[0];
+assign PIN_2_out_en = gpio1_io_out_en[0];
+assign PIN_3_out_data = gpio1_io_out_data[1];
+assign PIN_3_out_en = gpio1_io_out_en[1];
+assign PIN_1_out_data = gpio1_io_out_data[3];
+assign PIN_1_out_en = gpio1_io_out_en[3];
+assign PIN_92_out_data = gpio1_io_out_data[4];
+assign PIN_92_out_en = gpio1_io_out_en[4];
+assign PIN_91_out_data = gpio1_io_out_data[5];
+assign PIN_91_out_en = gpio1_io_out_en[5];
+assign PIN_88_out_data = gpio1_io_out_data[6];
+assign PIN_88_out_en = gpio1_io_out_en[6];
+(* keep = 1 *) wire [7:0] gpio1_io_in = {1'b0, PIN_88_in, PIN_91_in, PIN_92_in, PIN_1_in, 1'b0, PIN_3_in, PIN_2_in};
+
+(* keep = 1 *) wire [7:0] gpio2_io_out_data;
+(* keep = 1 *) wire [7:0] gpio2_io_out_en;
+assign PIN_97_out_data = gpio2_io_out_data[0];
+assign PIN_97_out_en = gpio2_io_out_en[0];
+assign PIN_95_out_data = gpio2_io_out_data[1];
+assign PIN_95_out_en = gpio2_io_out_en[1];
+assign PIN_96_out_data = gpio2_io_out_data[2];
+assign PIN_96_out_en = gpio2_io_out_en[2];
+(* keep = 1 *) wire [7:0] gpio2_io_in = {1'b0, 1'b0, 1'b0, 1'b0, 1'b0, PIN_96_in, PIN_95_in, PIN_97_in};
+
+(* keep = 1 *) wire [7:0] gpio3_io_out_data;
+(* keep = 1 *) wire [7:0] gpio3_io_out_en;
+(* keep = 1 *) wire [7:0] gpio3_io_in = {1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0};
+
+(* keep = 1 *) wire [7:0] gpio4_io_out_data;
+(* keep = 1 *) wire [7:0] gpio4_io_out_en;
+(* keep = 1 *) wire [7:0] gpio4_io_in = {1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0};
+
+(* keep = 1 *) wire [7:0] gpio5_io_out_data;
+(* keep = 1 *) wire [7:0] gpio5_io_out_en;
+(* keep = 1 *) wire [7:0] gpio5_io_in = {1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0};
+
+(* keep = 1 *) wire [7:0] gpio6_io_out_data;
+(* keep = 1 *) wire [7:0] gpio6_io_out_en;
+(* keep = 1 *) wire [7:0] gpio6_io_in = {1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, PIN_69_in, 1'b0};
+
+(* keep = 1 *) wire [7:0] gpio7_io_out_data;
+(* keep = 1 *) wire [7:0] gpio7_io_out_en;
+assign PIN_68_out_data = gpio7_io_out_data[6];
+assign PIN_68_out_en = gpio7_io_out_en[6];
+(* keep = 1 *) wire [7:0] gpio7_io_in = {1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0};
+
+(* keep = 1 *) wire [7:0] gpio8_io_out_data;
+(* keep = 1 *) wire [7:0] gpio8_io_out_en;
+(* keep = 1 *) wire [7:0] gpio8_io_in = {1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0};
+
+(* keep = 1 *) wire [7:0] gpio9_io_out_data;
+(* keep = 1 *) wire [7:0] gpio9_io_out_en;
+(* keep = 1 *) wire [7:0] gpio9_io_in = {1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0};
+
+alta_rv32 rv32(
+  .sys_clk            (sys_clk                                         ),
+  .sys_ctrl_stop      (sys_ctrl_stop                                   ),
+  .sys_ctrl_clkSource (sys_ctrl_clkSource                              ),
+  .resetn_out         (sys_resetn                                      ),
+  .sys_ctrl_pllEnable (PLL_ENABLE                                      ),
+  .sys_ctrl_pllReady  (PLL_LOCK                                        ),
+  .ext_resetn         (1'b1                                            ),
+  .test_mode          (2'b0                                            ),
+  .usb0_xcvr_clk      (usb0_xcvr_clk                                   ),
+  .usb0_id            (1'b1                                            ),
+  .ext_int            ({1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0}),
+  .mem_ahb_htrans     (mem_ahb_htrans                                  ),
+  .mem_ahb_hready     (mem_ahb_hready                                  ),
+  .mem_ahb_hwrite     (mem_ahb_hwrite                                  ),
+  .mem_ahb_haddr      (mem_ahb_haddr                                   ),
+  .mem_ahb_hsize      (mem_ahb_hsize                                   ),
+  .mem_ahb_hburst     (mem_ahb_hburst                                  ),
+  .mem_ahb_hwdata     (mem_ahb_hwdata                                  ),
+  .mem_ahb_hreadyout  (mem_ahb_hreadyout                               ),
+  .mem_ahb_hresp      (mem_ahb_hresp                                   ),
+  .mem_ahb_hrdata     (mem_ahb_hrdata                                  ),
+  .slave_ahb_hsel     (slave_ahb_hsel                                  ),
+  .slave_ahb_hready   (slave_ahb_hready                                ),
+  .slave_ahb_hreadyout(slave_ahb_hreadyout                             ),
+  .slave_ahb_htrans   (slave_ahb_htrans                                ),
+  .slave_ahb_hsize    (slave_ahb_hsize                                 ),
+  .slave_ahb_hburst   (slave_ahb_hburst                                ),
+  .slave_ahb_hwrite   (slave_ahb_hwrite                                ),
+  .slave_ahb_haddr    (slave_ahb_haddr                                 ),
+  .slave_ahb_hwdata   (slave_ahb_hwdata                                ),
+  .slave_ahb_hresp    (slave_ahb_hresp                                 ),
+  .slave_ahb_hrdata   (slave_ahb_hrdata                                ),
+  .ext_dma_DMACBREQ   (ext_dma_DMACBREQ                                ),
+  .ext_dma_DMACLBREQ  (ext_dma_DMACLBREQ                               ),
+  .ext_dma_DMACSREQ   (ext_dma_DMACSREQ                                ),
+  .ext_dma_DMACLSREQ  (ext_dma_DMACLSREQ                               ),
+  .ext_dma_DMACCLR    (ext_dma_DMACCLR                                 ),
+  .ext_dma_DMACTC     (ext_dma_DMACTC                                  ),
+  .local_int          (local_int                                       ),
+  .gpio0_io_in        (gpio0_io_in                                     ),
+  .gpio0_io_out_data  (gpio0_io_out_data                               ),
+  .gpio0_io_out_en    (gpio0_io_out_en                                 ),
+  .gpio1_io_in        (gpio1_io_in                                     ),
+  .gpio1_io_out_data  (gpio1_io_out_data                               ),
+  .gpio1_io_out_en    (gpio1_io_out_en                                 ),
+  .gpio2_io_in        (gpio2_io_in                                     ),
+  .gpio2_io_out_data  (gpio2_io_out_data                               ),
+  .gpio2_io_out_en    (gpio2_io_out_en                                 ),
+  .gpio3_io_in        (gpio3_io_in                                     ),
+  .gpio3_io_out_data  (gpio3_io_out_data                               ),
+  .gpio3_io_out_en    (gpio3_io_out_en                                 ),
+  .gpio4_io_in        (gpio4_io_in                                     ),
+  .gpio4_io_out_data  (gpio4_io_out_data                               ),
+  .gpio4_io_out_en    (gpio4_io_out_en                                 ),
+  .gpio5_io_in        (gpio5_io_in                                     ),
+  .gpio5_io_out_data  (gpio5_io_out_data                               ),
+  .gpio5_io_out_en    (gpio5_io_out_en                                 ),
+  .gpio6_io_in        (gpio6_io_in                                     ),
+  .gpio6_io_out_data  (gpio6_io_out_data                               ),
+  .gpio6_io_out_en    (gpio6_io_out_en                                 ),
+  .gpio7_io_in        (gpio7_io_in                                     ),
+  .gpio7_io_out_data  (gpio7_io_out_data                               ),
+  .gpio7_io_out_en    (gpio7_io_out_en                                 ),
+  .gpio8_io_in        (gpio8_io_in                                     ),
+  .gpio8_io_out_data  (gpio8_io_out_data                               ),
+  .gpio8_io_out_en    (gpio8_io_out_en                                 ),
+  .gpio9_io_in        (gpio9_io_in                                     ),
+  .gpio9_io_out_data  (gpio9_io_out_data                               ),
+  .gpio9_io_out_en    (gpio9_io_out_en                                 )
+);
+
+endmodule
+

+ 728 - 0
logic/boot_assignment_defaults.qdf

@@ -0,0 +1,728 @@
+# -------------------------------------------------------------------------- #
+#
+# Copyright (C) 1991-2015 Altera Corporation. All rights reserved.
+# Your use of Altera Corporation's design tools, logic functions 
+# and other software and tools, and its AMPP partner logic 
+# functions, and any output files from any of the foregoing 
+# (including device programming or simulation files), and any 
+# associated documentation or information are expressly subject 
+# to the terms and conditions of the Altera Program License 
+# Subscription Agreement, the Altera Quartus II License Agreement,
+# the Altera MegaCore Function License Agreement, or other 
+# applicable license agreement, including, without limitation, 
+# that your use is for the sole purpose of programming logic 
+# devices manufactured by Altera and sold by Altera or its 
+# authorized distributors.  Please refer to the applicable 
+# agreement for further details.
+#
+# -------------------------------------------------------------------------- #
+#
+# Quartus II 64-Bit
+# Version 15.0.0 Build 145 04/22/2015 SJ Full Version
+# Date created = 15:35:50  November 17, 2023
+#
+# -------------------------------------------------------------------------- #
+#
+# Note:
+#
+# 1) Do not modify this file. This file was generated
+#    automatically by the Quartus II software and is used
+#    to preserve global assignments across Quartus II versions.
+#
+# -------------------------------------------------------------------------- #
+
+set_global_assignment -name IP_COMPONENT_REPORT_HIERARCHY Off
+set_global_assignment -name IP_COMPONENT_INTERNAL Off
+set_global_assignment -name PROJECT_SHOW_ENTITY_NAME On
+set_global_assignment -name PROJECT_USE_SIMPLIFIED_NAMES Off
+set_global_assignment -name ENABLE_REDUCED_MEMORY_MODE Off
+set_global_assignment -name VER_COMPATIBLE_DB_DIR export_db
+set_global_assignment -name AUTO_EXPORT_VER_COMPATIBLE_DB Off
+set_global_assignment -name FLOW_DISABLE_ASSEMBLER Off
+set_global_assignment -name FLOW_ENABLE_POWER_ANALYZER Off
+set_global_assignment -name FLOW_ENABLE_HC_COMPARE Off
+set_global_assignment -name HC_OUTPUT_DIR hc_output
+set_global_assignment -name SAVE_MIGRATION_INFO_DURING_COMPILATION Off
+set_global_assignment -name FLOW_ENABLE_IO_ASSIGNMENT_ANALYSIS Off
+set_global_assignment -name RUN_FULL_COMPILE_ON_DEVICE_CHANGE On
+set_global_assignment -name FLOW_ENABLE_RTL_VIEWER Off
+set_global_assignment -name READ_OR_WRITE_IN_BYTE_ADDRESS "Use global settings"
+set_global_assignment -name FLOW_HARDCOPY_DESIGN_READINESS_CHECK On
+set_global_assignment -name FLOW_ENABLE_PARALLEL_MODULES On
+set_global_assignment -name ENABLE_COMPACT_REPORT_TABLE Off
+set_global_assignment -name REVISION_TYPE Base
+set_global_assignment -name DEFAULT_HOLD_MULTICYCLE "Same as Multicycle"
+set_global_assignment -name CUT_OFF_PATHS_BETWEEN_CLOCK_DOMAINS On
+set_global_assignment -name CUT_OFF_READ_DURING_WRITE_PATHS On
+set_global_assignment -name CUT_OFF_IO_PIN_FEEDBACK On
+set_global_assignment -name DO_COMBINED_ANALYSIS Off
+set_global_assignment -name TDC_AGGRESSIVE_HOLD_CLOSURE_EFFORT Off
+set_global_assignment -name EMIF_SOC_PHYCLK_ADVANCE_MODELING Off
+set_global_assignment -name USE_DLL_FREQUENCY_FOR_DQS_DELAY_CHAIN Off
+set_global_assignment -name ANALYZE_LATCHES_AS_SYNCHRONOUS_ELEMENTS On
+set_global_assignment -name TIMEQUEST_REPORT_SCRIPT_INCLUDE_DEFAULT_ANALYSIS On
+set_global_assignment -name TIMEQUEST_MULTICORNER_ANALYSIS On -family "Arria V"
+set_global_assignment -name TIMEQUEST_MULTICORNER_ANALYSIS On -family "MAX 10"
+set_global_assignment -name TIMEQUEST_MULTICORNER_ANALYSIS On -family "Stratix IV"
+set_global_assignment -name TIMEQUEST_MULTICORNER_ANALYSIS On -family "Cyclone IV E"
+set_global_assignment -name TIMEQUEST_MULTICORNER_ANALYSIS On -family "Arria 10"
+set_global_assignment -name TIMEQUEST_MULTICORNER_ANALYSIS Off -family "MAX V"
+set_global_assignment -name TIMEQUEST_MULTICORNER_ANALYSIS On -family "Stratix V"
+set_global_assignment -name TIMEQUEST_MULTICORNER_ANALYSIS On -family "Arria V GZ"
+set_global_assignment -name TIMEQUEST_MULTICORNER_ANALYSIS Off -family "MAX II"
+set_global_assignment -name TIMEQUEST_MULTICORNER_ANALYSIS On -family "Arria II GX"
+set_global_assignment -name TIMEQUEST_MULTICORNER_ANALYSIS On -family "Arria II GZ"
+set_global_assignment -name TIMEQUEST_MULTICORNER_ANALYSIS On -family "Cyclone IV GX"
+set_global_assignment -name TIMEQUEST_MULTICORNER_ANALYSIS On -family "Cyclone V"
+set_global_assignment -name TIMEQUEST_DO_REPORT_TIMING Off
+set_global_assignment -name TIMEQUEST_REPORT_WORST_CASE_TIMING_PATHS Off -family "Arria V"
+set_global_assignment -name TIMEQUEST_REPORT_WORST_CASE_TIMING_PATHS Off -family "MAX 10"
+set_global_assignment -name TIMEQUEST_REPORT_WORST_CASE_TIMING_PATHS Off -family "Stratix IV"
+set_global_assignment -name TIMEQUEST_REPORT_WORST_CASE_TIMING_PATHS On -family "Cyclone IV E"
+set_global_assignment -name TIMEQUEST_REPORT_WORST_CASE_TIMING_PATHS Off -family "Arria 10"
+set_global_assignment -name TIMEQUEST_REPORT_WORST_CASE_TIMING_PATHS On -family "MAX V"
+set_global_assignment -name TIMEQUEST_REPORT_WORST_CASE_TIMING_PATHS Off -family "Stratix V"
+set_global_assignment -name TIMEQUEST_REPORT_WORST_CASE_TIMING_PATHS Off -family "Arria V GZ"
+set_global_assignment -name TIMEQUEST_REPORT_WORST_CASE_TIMING_PATHS On -family "MAX II"
+set_global_assignment -name TIMEQUEST_REPORT_WORST_CASE_TIMING_PATHS Off -family "Arria II GX"
+set_global_assignment -name TIMEQUEST_REPORT_WORST_CASE_TIMING_PATHS Off -family "Arria II GZ"
+set_global_assignment -name TIMEQUEST_REPORT_WORST_CASE_TIMING_PATHS On -family "Cyclone IV GX"
+set_global_assignment -name TIMEQUEST_REPORT_WORST_CASE_TIMING_PATHS Off -family "Cyclone V"
+set_global_assignment -name TIMEQUEST_REPORT_NUM_WORST_CASE_TIMING_PATHS 100
+set_global_assignment -name TIMEQUEST_DO_CCPP_REMOVAL On -family "Arria V"
+set_global_assignment -name TIMEQUEST_DO_CCPP_REMOVAL On -family "MAX 10"
+set_global_assignment -name TIMEQUEST_DO_CCPP_REMOVAL On -family "Cyclone IV E"
+set_global_assignment -name TIMEQUEST_DO_CCPP_REMOVAL On -family "Stratix IV"
+set_global_assignment -name TIMEQUEST_DO_CCPP_REMOVAL On -family "Arria 10"
+set_global_assignment -name TIMEQUEST_DO_CCPP_REMOVAL Off -family "MAX V"
+set_global_assignment -name TIMEQUEST_DO_CCPP_REMOVAL On -family "Stratix V"
+set_global_assignment -name TIMEQUEST_DO_CCPP_REMOVAL On -family "Arria V GZ"
+set_global_assignment -name TIMEQUEST_DO_CCPP_REMOVAL Off -family "MAX II"
+set_global_assignment -name TIMEQUEST_DO_CCPP_REMOVAL On -family "Arria II GX"
+set_global_assignment -name TIMEQUEST_DO_CCPP_REMOVAL On -family "Arria II GZ"
+set_global_assignment -name TIMEQUEST_DO_CCPP_REMOVAL On -family "Cyclone IV GX"
+set_global_assignment -name TIMEQUEST_DO_CCPP_REMOVAL On -family "Cyclone V"
+set_global_assignment -name OPTIMIZATION_MODE Balanced
+set_global_assignment -name ALLOW_REGISTER_MERGING On
+set_global_assignment -name ALLOW_REGISTER_DUPLICATION On
+set_global_assignment -name TIMEQUEST2 on -family "Arria 10"
+set_global_assignment -name TIMEQUEST2 OFF -family "Stratix V"
+set_global_assignment -name MUX_RESTRUCTURE Auto
+set_global_assignment -name MLAB_ADD_TIMING_CONSTRAINTS_FOR_MIXED_PORT_FEED_THROUGH_MODE_SETTING_DONT_CARE Off
+set_global_assignment -name ENABLE_IP_DEBUG Off
+set_global_assignment -name SAVE_DISK_SPACE On
+set_global_assignment -name DISABLE_OCP_HW_EVAL Off
+set_global_assignment -name DEVICE_FILTER_PACKAGE Any
+set_global_assignment -name DEVICE_FILTER_PIN_COUNT Any
+set_global_assignment -name DEVICE_FILTER_SPEED_GRADE Any
+set_global_assignment -name EDA_DESIGN_ENTRY_SYNTHESIS_TOOL "<None>"
+set_global_assignment -name VERILOG_INPUT_VERSION Verilog_2001
+set_global_assignment -name VHDL_INPUT_VERSION VHDL_1993
+set_global_assignment -name FAMILY -value "Cyclone V"
+set_global_assignment -name TRUE_WYSIWYG_FLOW Off
+set_global_assignment -name SMART_COMPILE_IGNORES_TDC_FOR_STRATIX_PLL_CHANGES Off
+set_global_assignment -name STATE_MACHINE_PROCESSING Auto
+set_global_assignment -name SAFE_STATE_MACHINE Off
+set_global_assignment -name EXTRACT_VERILOG_STATE_MACHINES On
+set_global_assignment -name EXTRACT_VHDL_STATE_MACHINES On
+set_global_assignment -name IGNORE_VERILOG_INITIAL_CONSTRUCTS Off
+set_global_assignment -name VERILOG_CONSTANT_LOOP_LIMIT 5000
+set_global_assignment -name VERILOG_NON_CONSTANT_LOOP_LIMIT 250
+set_global_assignment -name INFER_RAMS_FROM_RAW_LOGIC On
+set_global_assignment -name PARALLEL_SYNTHESIS On
+set_global_assignment -name DSP_BLOCK_BALANCING Auto
+set_global_assignment -name MAX_BALANCING_DSP_BLOCKS "-1 (Unlimited)"
+set_global_assignment -name NOT_GATE_PUSH_BACK On
+set_global_assignment -name ALLOW_POWER_UP_DONT_CARE On
+set_global_assignment -name REMOVE_REDUNDANT_LOGIC_CELLS Off
+set_global_assignment -name REMOVE_DUPLICATE_REGISTERS On
+set_global_assignment -name IGNORE_CARRY_BUFFERS Off
+set_global_assignment -name IGNORE_CASCADE_BUFFERS Off
+set_global_assignment -name IGNORE_GLOBAL_BUFFERS Off
+set_global_assignment -name IGNORE_ROW_GLOBAL_BUFFERS Off
+set_global_assignment -name IGNORE_LCELL_BUFFERS Off
+set_global_assignment -name MAX7000_IGNORE_LCELL_BUFFERS AUTO
+set_global_assignment -name IGNORE_SOFT_BUFFERS On
+set_global_assignment -name MAX7000_IGNORE_SOFT_BUFFERS Off
+set_global_assignment -name LIMIT_AHDL_INTEGERS_TO_32_BITS Off
+set_global_assignment -name AUTO_GLOBAL_CLOCK_MAX On
+set_global_assignment -name AUTO_GLOBAL_OE_MAX On
+set_global_assignment -name MAX_AUTO_GLOBAL_REGISTER_CONTROLS On
+set_global_assignment -name AUTO_IMPLEMENT_IN_ROM Off
+set_global_assignment -name APEX20K_TECHNOLOGY_MAPPER Lut
+set_global_assignment -name OPTIMIZATION_TECHNIQUE Balanced
+set_global_assignment -name STRATIXII_OPTIMIZATION_TECHNIQUE Balanced
+set_global_assignment -name CYCLONE_OPTIMIZATION_TECHNIQUE Balanced
+set_global_assignment -name CYCLONEII_OPTIMIZATION_TECHNIQUE Balanced
+set_global_assignment -name STRATIX_OPTIMIZATION_TECHNIQUE Balanced
+set_global_assignment -name MAXII_OPTIMIZATION_TECHNIQUE Balanced
+set_global_assignment -name MAX7000_OPTIMIZATION_TECHNIQUE Speed
+set_global_assignment -name APEX20K_OPTIMIZATION_TECHNIQUE Balanced
+set_global_assignment -name MERCURY_OPTIMIZATION_TECHNIQUE Area
+set_global_assignment -name FLEX6K_OPTIMIZATION_TECHNIQUE Area
+set_global_assignment -name FLEX10K_OPTIMIZATION_TECHNIQUE Area
+set_global_assignment -name ALLOW_XOR_GATE_USAGE On
+set_global_assignment -name AUTO_LCELL_INSERTION On
+set_global_assignment -name CARRY_CHAIN_LENGTH 48
+set_global_assignment -name FLEX6K_CARRY_CHAIN_LENGTH 32
+set_global_assignment -name FLEX10K_CARRY_CHAIN_LENGTH 32
+set_global_assignment -name MERCURY_CARRY_CHAIN_LENGTH 48
+set_global_assignment -name STRATIX_CARRY_CHAIN_LENGTH 70
+set_global_assignment -name STRATIXII_CARRY_CHAIN_LENGTH 70
+set_global_assignment -name CASCADE_CHAIN_LENGTH 2
+set_global_assignment -name PARALLEL_EXPANDER_CHAIN_LENGTH 16
+set_global_assignment -name MAX7000_PARALLEL_EXPANDER_CHAIN_LENGTH 4
+set_global_assignment -name AUTO_CARRY_CHAINS On
+set_global_assignment -name AUTO_CASCADE_CHAINS On
+set_global_assignment -name AUTO_PARALLEL_EXPANDERS On
+set_global_assignment -name AUTO_OPEN_DRAIN_PINS On
+set_global_assignment -name ADV_NETLIST_OPT_SYNTH_WYSIWYG_REMAP Off
+set_global_assignment -name AUTO_ROM_RECOGNITION On
+set_global_assignment -name AUTO_RAM_RECOGNITION On
+set_global_assignment -name AUTO_DSP_RECOGNITION On
+set_global_assignment -name AUTO_SHIFT_REGISTER_RECOGNITION Auto
+set_global_assignment -name ALLOW_SHIFT_REGISTER_MERGING_ACROSS_HIERARCHIES Auto
+set_global_assignment -name AUTO_CLOCK_ENABLE_RECOGNITION On
+set_global_assignment -name STRICT_RAM_RECOGNITION Off
+set_global_assignment -name ALLOW_SYNCH_CTRL_USAGE On
+set_global_assignment -name FORCE_SYNCH_CLEAR Off
+set_global_assignment -name AUTO_RAM_BLOCK_BALANCING On
+set_global_assignment -name AUTO_RAM_TO_LCELL_CONVERSION Off
+set_global_assignment -name AUTO_RESOURCE_SHARING Off
+set_global_assignment -name ALLOW_ANY_RAM_SIZE_FOR_RECOGNITION Off
+set_global_assignment -name ALLOW_ANY_ROM_SIZE_FOR_RECOGNITION Off
+set_global_assignment -name ALLOW_ANY_SHIFT_REGISTER_SIZE_FOR_RECOGNITION Off
+set_global_assignment -name MAX7000_FANIN_PER_CELL 100
+set_global_assignment -name USE_LOGICLOCK_CONSTRAINTS_IN_BALANCING On
+set_global_assignment -name MAX_RAM_BLOCKS_M512 "-1 (Unlimited)"
+set_global_assignment -name MAX_RAM_BLOCKS_M4K "-1 (Unlimited)"
+set_global_assignment -name MAX_RAM_BLOCKS_MRAM "-1 (Unlimited)"
+set_global_assignment -name IGNORE_TRANSLATE_OFF_AND_SYNTHESIS_OFF Off
+set_global_assignment -name STRATIXGX_BYPASS_REMAPPING_OF_FORCE_SIGNAL_DETECT_SIGNAL_THRESHOLD_SELECT Off
+set_global_assignment -name SYNTH_TIMING_DRIVEN_SYNTHESIS On -family "Arria II GZ"
+set_global_assignment -name SYNTH_TIMING_DRIVEN_SYNTHESIS On -family "Arria V"
+set_global_assignment -name SYNTH_TIMING_DRIVEN_SYNTHESIS On -family "MAX 10"
+set_global_assignment -name SYNTH_TIMING_DRIVEN_SYNTHESIS On -family "Cyclone IV GX"
+set_global_assignment -name SYNTH_TIMING_DRIVEN_SYNTHESIS On -family "Stratix IV"
+set_global_assignment -name SYNTH_TIMING_DRIVEN_SYNTHESIS On -family "Cyclone IV E"
+set_global_assignment -name SYNTH_TIMING_DRIVEN_SYNTHESIS On -family "Arria 10"
+set_global_assignment -name SYNTH_TIMING_DRIVEN_SYNTHESIS On -family "Stratix V"
+set_global_assignment -name SYNTH_TIMING_DRIVEN_SYNTHESIS On -family "Arria V GZ"
+set_global_assignment -name SYNTH_TIMING_DRIVEN_SYNTHESIS On -family "Cyclone V"
+set_global_assignment -name SYNTH_TIMING_DRIVEN_SYNTHESIS On -family "Arria II GX"
+set_global_assignment -name REPORT_PARAMETER_SETTINGS On
+set_global_assignment -name REPORT_SOURCE_ASSIGNMENTS On
+set_global_assignment -name REPORT_CONNECTIVITY_CHECKS On
+set_global_assignment -name IGNORE_MAX_FANOUT_ASSIGNMENTS Off
+set_global_assignment -name SYNCHRONIZATION_REGISTER_CHAIN_LENGTH 3 -family "Arria V"
+set_global_assignment -name SYNCHRONIZATION_REGISTER_CHAIN_LENGTH 2 -family "MAX 10"
+set_global_assignment -name SYNCHRONIZATION_REGISTER_CHAIN_LENGTH 2 -family "Cyclone IV E"
+set_global_assignment -name SYNCHRONIZATION_REGISTER_CHAIN_LENGTH 3 -family "Stratix IV"
+set_global_assignment -name SYNCHRONIZATION_REGISTER_CHAIN_LENGTH 3 -family "Arria 10"
+set_global_assignment -name SYNCHRONIZATION_REGISTER_CHAIN_LENGTH 2 -family "MAX V"
+set_global_assignment -name SYNCHRONIZATION_REGISTER_CHAIN_LENGTH 3 -family "Stratix V"
+set_global_assignment -name SYNCHRONIZATION_REGISTER_CHAIN_LENGTH 2 -family "MAX II"
+set_global_assignment -name SYNCHRONIZATION_REGISTER_CHAIN_LENGTH 3 -family "Arria V GZ"
+set_global_assignment -name SYNCHRONIZATION_REGISTER_CHAIN_LENGTH 3 -family "Arria II GX"
+set_global_assignment -name SYNCHRONIZATION_REGISTER_CHAIN_LENGTH 3 -family "Arria II GZ"
+set_global_assignment -name SYNCHRONIZATION_REGISTER_CHAIN_LENGTH 2 -family "Cyclone IV GX"
+set_global_assignment -name SYNCHRONIZATION_REGISTER_CHAIN_LENGTH 3 -family "Cyclone V"
+set_global_assignment -name OPTIMIZE_POWER_DURING_SYNTHESIS "Normal compilation"
+set_global_assignment -name HDL_MESSAGE_LEVEL Level2
+set_global_assignment -name USE_HIGH_SPEED_ADDER Auto
+set_global_assignment -name NUMBER_OF_REMOVED_REGISTERS_REPORTED 5000
+set_global_assignment -name NUMBER_OF_SYNTHESIS_MIGRATION_ROWS 5000
+set_global_assignment -name SYNTHESIS_S10_MIGRATION_CHECKS Off
+set_global_assignment -name NUMBER_OF_SWEPT_NODES_REPORTED 5000
+set_global_assignment -name NUMBER_OF_INVERTED_REGISTERS_REPORTED 100
+set_global_assignment -name SYNTH_CLOCK_MUX_PROTECTION On
+set_global_assignment -name SYNTH_GATED_CLOCK_CONVERSION Off
+set_global_assignment -name BLOCK_DESIGN_NAMING Auto
+set_global_assignment -name SYNTH_PROTECT_SDC_CONSTRAINT Off
+set_global_assignment -name SYNTHESIS_EFFORT Auto
+set_global_assignment -name SHIFT_REGISTER_RECOGNITION_ACLR_SIGNAL On
+set_global_assignment -name PRE_MAPPING_RESYNTHESIS Off
+set_global_assignment -name SYNTH_MESSAGE_LEVEL Medium
+set_global_assignment -name DISABLE_REGISTER_MERGING_ACROSS_HIERARCHIES Auto
+set_global_assignment -name SYNTH_RESOURCE_AWARE_INFERENCE_FOR_BLOCK_RAM On -family "Arria II GZ"
+set_global_assignment -name SYNTH_RESOURCE_AWARE_INFERENCE_FOR_BLOCK_RAM On -family "Arria V"
+set_global_assignment -name SYNTH_RESOURCE_AWARE_INFERENCE_FOR_BLOCK_RAM On -family "MAX 10"
+set_global_assignment -name SYNTH_RESOURCE_AWARE_INFERENCE_FOR_BLOCK_RAM On -family "Cyclone IV GX"
+set_global_assignment -name SYNTH_RESOURCE_AWARE_INFERENCE_FOR_BLOCK_RAM On -family "Stratix IV"
+set_global_assignment -name SYNTH_RESOURCE_AWARE_INFERENCE_FOR_BLOCK_RAM On -family "Cyclone IV E"
+set_global_assignment -name SYNTH_RESOURCE_AWARE_INFERENCE_FOR_BLOCK_RAM On -family "Arria 10"
+set_global_assignment -name SYNTH_RESOURCE_AWARE_INFERENCE_FOR_BLOCK_RAM On -family "Stratix V"
+set_global_assignment -name SYNTH_RESOURCE_AWARE_INFERENCE_FOR_BLOCK_RAM On -family "Arria V GZ"
+set_global_assignment -name SYNTH_RESOURCE_AWARE_INFERENCE_FOR_BLOCK_RAM On -family "Cyclone V"
+set_global_assignment -name SYNTH_RESOURCE_AWARE_INFERENCE_FOR_BLOCK_RAM On -family "Arria II GX"
+set_global_assignment -name MAX_LABS "-1 (Unlimited)"
+set_global_assignment -name RBCGEN_CRITICAL_WARNING_TO_ERROR On
+set_global_assignment -name MAX_NUMBER_OF_REGISTERS_FROM_UNINFERRED_RAMS "-1 (Unlimited)"
+set_global_assignment -name AUTO_PARALLEL_SYNTHESIS On
+set_global_assignment -name PRPOF_ID Off
+set_global_assignment -name DISABLE_DSP_NEGATE_INFERENCING Off
+set_global_assignment -name FLEX10K_ENABLE_LOCK_OUTPUT Off
+set_global_assignment -name AUTO_MERGE_PLLS On
+set_global_assignment -name IGNORE_MODE_FOR_MERGE Off
+set_global_assignment -name TXPMA_SLEW_RATE Low
+set_global_assignment -name ADCE_ENABLED Auto
+set_global_assignment -name ROUTER_TIMING_OPTIMIZATION_LEVEL Normal
+set_global_assignment -name ROUTER_CLOCKING_TOPOLOGY_ANALYSIS Off
+set_global_assignment -name PLACEMENT_EFFORT_MULTIPLIER 1.0
+set_global_assignment -name ROUTER_EFFORT_MULTIPLIER 1.0
+set_global_assignment -name FIT_ATTEMPTS_TO_SKIP 0.0
+set_global_assignment -name ECO_ALLOW_ROUTING_CHANGES Off
+set_global_assignment -name DEVICE AUTO
+set_global_assignment -name BASE_PIN_OUT_FILE_ON_SAMEFRAME_DEVICE Off
+set_global_assignment -name ENABLE_JTAG_BST_SUPPORT Off
+set_global_assignment -name MAX7000_ENABLE_JTAG_BST_SUPPORT On
+set_global_assignment -name ENABLE_NCEO_OUTPUT Off
+set_global_assignment -name RESERVE_NCEO_AFTER_CONFIGURATION "Use as regular IO"
+set_global_assignment -name CYCLONEII_RESERVE_NCEO_AFTER_CONFIGURATION "Use as programming pin"
+set_global_assignment -name STRATIXIII_UPDATE_MODE Standard
+set_global_assignment -name STRATIX_UPDATE_MODE Standard
+set_global_assignment -name INTERNAL_FLASH_UPDATE_MODE "Single Image"
+set_global_assignment -name CVP_MODE Off
+set_global_assignment -name STRATIXV_CONFIGURATION_SCHEME "Passive Serial"
+set_global_assignment -name STRATIXIII_CONFIGURATION_SCHEME "Passive Serial"
+set_global_assignment -name MAX10FPGA_CONFIGURATION_SCHEME "Internal Configuration"
+set_global_assignment -name CYCLONEIII_CONFIGURATION_SCHEME "Active Serial"
+set_global_assignment -name STRATIXII_CONFIGURATION_SCHEME "Passive Serial"
+set_global_assignment -name CYCLONEII_CONFIGURATION_SCHEME "Active Serial"
+set_global_assignment -name APEX20K_CONFIGURATION_SCHEME "Passive Serial"
+set_global_assignment -name STRATIX_CONFIGURATION_SCHEME "Passive Serial"
+set_global_assignment -name CYCLONE_CONFIGURATION_SCHEME "Active Serial"
+set_global_assignment -name MERCURY_CONFIGURATION_SCHEME "Passive Serial"
+set_global_assignment -name FLEX6K_CONFIGURATION_SCHEME "Passive Serial"
+set_global_assignment -name FLEX10K_CONFIGURATION_SCHEME "Passive Serial"
+set_global_assignment -name APEXII_CONFIGURATION_SCHEME "Passive Serial"
+set_global_assignment -name USER_START_UP_CLOCK Off
+set_global_assignment -name DEVICE_INITIALIZATION_CLOCK INIT_INTOSC
+set_global_assignment -name ENABLE_VREFA_PIN Off
+set_global_assignment -name ENABLE_VREFB_PIN Off
+set_global_assignment -name ALWAYS_ENABLE_INPUT_BUFFERS Off
+set_global_assignment -name ENABLE_ASMI_FOR_FLASH_LOADER Off
+set_global_assignment -name ENABLE_DEVICE_WIDE_RESET Off
+set_global_assignment -name ENABLE_DEVICE_WIDE_OE Off
+set_global_assignment -name RESERVE_ALL_UNUSED_PINS "As output driving ground"
+set_global_assignment -name ENABLE_INIT_DONE_OUTPUT Off
+set_global_assignment -name INIT_DONE_OPEN_DRAIN On
+set_global_assignment -name RESERVE_NWS_NRS_NCS_CS_AFTER_CONFIGURATION "Use as regular IO"
+set_global_assignment -name RESERVE_RDYNBUSY_AFTER_CONFIGURATION "Use as regular IO"
+set_global_assignment -name RESERVE_DATA31_THROUGH_DATA16_AFTER_CONFIGURATION "Use as regular IO"
+set_global_assignment -name RESERVE_DATA15_THROUGH_DATA8_AFTER_CONFIGURATION "Use as regular IO"
+set_global_assignment -name RESERVE_DATA7_THROUGH_DATA1_AFTER_CONFIGURATION "Use as regular IO"
+set_global_assignment -name RESERVE_DATA0_AFTER_CONFIGURATION "As input tri-stated"
+set_global_assignment -name RESERVE_DATA1_AFTER_CONFIGURATION "As input tri-stated"
+set_global_assignment -name RESERVE_DATA7_THROUGH_DATA2_AFTER_CONFIGURATION "Use as regular IO"
+set_global_assignment -name RESERVE_DATA7_THROUGH_DATA5_AFTER_CONFIGURATION "Use as regular IO"
+set_global_assignment -name RESERVE_FLASH_NCE_AFTER_CONFIGURATION "As input tri-stated"
+set_global_assignment -name RESERVE_OTHER_AP_PINS_AFTER_CONFIGURATION "Use as regular IO"
+set_global_assignment -name RESERVE_DCLK_AFTER_CONFIGURATION "Use as programming pin"
+set_global_assignment -name ENABLE_CONFIGURATION_PINS On
+set_global_assignment -name ENABLE_JTAG_PIN_SHARING Off
+set_global_assignment -name ENABLE_NCE_PIN Off
+set_global_assignment -name ENABLE_BOOT_SEL_PIN On
+set_global_assignment -name CRC_ERROR_CHECKING Off
+set_global_assignment -name INTERNAL_SCRUBBING Off
+set_global_assignment -name PR_ERROR_OPEN_DRAIN On
+set_global_assignment -name PR_READY_OPEN_DRAIN On
+set_global_assignment -name ENABLE_CVP_CONFDONE Off
+set_global_assignment -name CVP_CONFDONE_OPEN_DRAIN On
+set_global_assignment -name ENABLE_NCONFIG_FROM_CORE On
+set_global_assignment -name OPTIMIZE_HOLD_TIMING "All Paths" -family "Arria II GZ"
+set_global_assignment -name OPTIMIZE_HOLD_TIMING "All Paths" -family "Arria V"
+set_global_assignment -name OPTIMIZE_HOLD_TIMING "All Paths" -family "MAX 10"
+set_global_assignment -name OPTIMIZE_HOLD_TIMING "All Paths" -family "Cyclone IV GX"
+set_global_assignment -name OPTIMIZE_HOLD_TIMING "All Paths" -family "Stratix IV"
+set_global_assignment -name OPTIMIZE_HOLD_TIMING "All Paths" -family "Cyclone IV E"
+set_global_assignment -name OPTIMIZE_HOLD_TIMING "All Paths" -family "Arria 10"
+set_global_assignment -name OPTIMIZE_HOLD_TIMING "IO Paths and Minimum TPD Paths" -family "MAX V"
+set_global_assignment -name OPTIMIZE_HOLD_TIMING "All Paths" -family "Stratix V"
+set_global_assignment -name OPTIMIZE_HOLD_TIMING "IO Paths and Minimum TPD Paths" -family "MAX II"
+set_global_assignment -name OPTIMIZE_HOLD_TIMING "All Paths" -family "Arria V GZ"
+set_global_assignment -name OPTIMIZE_HOLD_TIMING "All Paths" -family "Cyclone V"
+set_global_assignment -name OPTIMIZE_HOLD_TIMING "All Paths" -family "Arria II GX"
+set_global_assignment -name OPTIMIZE_MULTI_CORNER_TIMING On -family "Arria V"
+set_global_assignment -name OPTIMIZE_MULTI_CORNER_TIMING On -family "MAX 10"
+set_global_assignment -name OPTIMIZE_MULTI_CORNER_TIMING On -family "Cyclone IV E"
+set_global_assignment -name OPTIMIZE_MULTI_CORNER_TIMING On -family "Stratix IV"
+set_global_assignment -name OPTIMIZE_MULTI_CORNER_TIMING On -family "Arria 10"
+set_global_assignment -name OPTIMIZE_MULTI_CORNER_TIMING Off -family "MAX V"
+set_global_assignment -name OPTIMIZE_MULTI_CORNER_TIMING On -family "Stratix V"
+set_global_assignment -name OPTIMIZE_MULTI_CORNER_TIMING On -family "Arria V GZ"
+set_global_assignment -name OPTIMIZE_MULTI_CORNER_TIMING Off -family "MAX II"
+set_global_assignment -name OPTIMIZE_MULTI_CORNER_TIMING On -family "Arria II GX"
+set_global_assignment -name OPTIMIZE_MULTI_CORNER_TIMING On -family "Arria II GZ"
+set_global_assignment -name OPTIMIZE_MULTI_CORNER_TIMING On -family "Cyclone IV GX"
+set_global_assignment -name OPTIMIZE_MULTI_CORNER_TIMING On -family "Cyclone V"
+set_global_assignment -name BLOCK_RAM_TO_MLAB_CELL_CONVERSION On
+set_global_assignment -name BLOCK_RAM_AND_MLAB_EQUIVALENT_POWER_UP_CONDITIONS Auto
+set_global_assignment -name BLOCK_RAM_AND_MLAB_EQUIVALENT_PAUSED_READ_CAPABILITIES Care
+set_global_assignment -name PROGRAMMABLE_POWER_TECHNOLOGY_SETTING Automatic -family "Stratix IV"
+set_global_assignment -name PROGRAMMABLE_POWER_TECHNOLOGY_SETTING Automatic -family "Arria 10"
+set_global_assignment -name PROGRAMMABLE_POWER_TECHNOLOGY_SETTING Automatic -family "Stratix V"
+set_global_assignment -name PROGRAMMABLE_POWER_TECHNOLOGY_SETTING Automatic -family "Arria V GZ"
+set_global_assignment -name PROGRAMMABLE_POWER_MAXIMUM_HIGH_SPEED_FRACTION_OF_USED_LAB_TILES 1.0
+set_global_assignment -name GUARANTEE_MIN_DELAY_CORNER_IO_ZERO_HOLD_TIME On
+set_global_assignment -name OPTIMIZE_POWER_DURING_FITTING "Normal compilation"
+set_global_assignment -name OPTIMIZE_SSN Off
+set_global_assignment -name OPTIMIZE_TIMING "Normal compilation"
+set_global_assignment -name ECO_OPTIMIZE_TIMING Off
+set_global_assignment -name ECO_REGENERATE_REPORT Off
+set_global_assignment -name OPTIMIZE_IOC_REGISTER_PLACEMENT_FOR_TIMING Normal
+set_global_assignment -name FIT_ONLY_ONE_ATTEMPT Off
+set_global_assignment -name FINAL_PLACEMENT_OPTIMIZATION Automatically
+set_global_assignment -name FITTER_AGGRESSIVE_ROUTABILITY_OPTIMIZATION Automatically
+set_global_assignment -name SEED 1
+set_global_assignment -name SLOW_SLEW_RATE Off
+set_global_assignment -name PCI_IO Off
+set_global_assignment -name TURBO_BIT On
+set_global_assignment -name WEAK_PULL_UP_RESISTOR Off
+set_global_assignment -name ENABLE_BUS_HOLD_CIRCUITRY Off
+set_global_assignment -name AUTO_GLOBAL_MEMORY_CONTROLS Off
+set_global_assignment -name MIGRATION_CONSTRAIN_CORE_RESOURCES On
+set_global_assignment -name QII_AUTO_PACKED_REGISTERS Auto
+set_global_assignment -name AUTO_PACKED_REGISTERS_MAX Auto
+set_global_assignment -name NORMAL_LCELL_INSERT On
+set_global_assignment -name CARRY_OUT_PINS_LCELL_INSERT On
+set_global_assignment -name AUTO_DELAY_CHAINS On -family "Arria V"
+set_global_assignment -name AUTO_DELAY_CHAINS On -family "MAX 10"
+set_global_assignment -name AUTO_DELAY_CHAINS On -family "Stratix IV"
+set_global_assignment -name AUTO_DELAY_CHAINS On -family "Cyclone IV E"
+set_global_assignment -name AUTO_DELAY_CHAINS Off -family "Arria 10"
+set_global_assignment -name AUTO_DELAY_CHAINS On -family "MAX V"
+set_global_assignment -name AUTO_DELAY_CHAINS On -family "Stratix V"
+set_global_assignment -name AUTO_DELAY_CHAINS On -family "MAX II"
+set_global_assignment -name AUTO_DELAY_CHAINS On -family "Arria V GZ"
+set_global_assignment -name AUTO_DELAY_CHAINS On -family "Arria II GX"
+set_global_assignment -name AUTO_DELAY_CHAINS On -family "Arria II GZ"
+set_global_assignment -name AUTO_DELAY_CHAINS On -family "Cyclone IV GX"
+set_global_assignment -name AUTO_DELAY_CHAINS On -family "Cyclone V"
+set_global_assignment -name AUTO_DELAY_CHAINS_FOR_HIGH_FANOUT_INPUT_PINS OFF
+set_global_assignment -name XSTL_INPUT_ALLOW_SE_BUFFER Off
+set_global_assignment -name TREAT_BIDIR_AS_OUTPUT Off
+set_global_assignment -name AUTO_TURBO_BIT ON
+set_global_assignment -name PHYSICAL_SYNTHESIS_COMBO_LOGIC_FOR_AREA Off
+set_global_assignment -name PHYSICAL_SYNTHESIS_COMBO_LOGIC Off
+set_global_assignment -name PHYSICAL_SYNTHESIS_LOG_FILE Off
+set_global_assignment -name PHYSICAL_SYNTHESIS_REGISTER_DUPLICATION Off
+set_global_assignment -name PHYSICAL_SYNTHESIS_MAP_LOGIC_TO_MEMORY_FOR_AREA Off
+set_global_assignment -name PHYSICAL_SYNTHESIS_REGISTER_RETIMING Off
+set_global_assignment -name PHYSICAL_SYNTHESIS_ASYNCHRONOUS_SIGNAL_PIPELINING Off
+set_global_assignment -name IO_PLACEMENT_OPTIMIZATION On
+set_global_assignment -name ALLOW_LVTTL_LVCMOS_INPUT_LEVELS_TO_OVERDRIVE_INPUT_BUFFER Off
+set_global_assignment -name OVERRIDE_DEFAULT_ELECTROMIGRATION_PARAMETERS Off
+set_global_assignment -name FITTER_EFFORT "Auto Fit"
+set_global_assignment -name FITTER_AUTO_EFFORT_DESIRED_SLACK_MARGIN 0ns
+set_global_assignment -name PHYSICAL_SYNTHESIS_EFFORT Normal
+set_global_assignment -name ROUTER_LCELL_INSERTION_AND_LOGIC_DUPLICATION Auto
+set_global_assignment -name ROUTER_REGISTER_DUPLICATION Auto
+set_global_assignment -name STRATIXGX_ALLOW_CLOCK_FANOUT_WITH_ANALOG_RESET Off
+set_global_assignment -name AUTO_GLOBAL_CLOCK On
+set_global_assignment -name AUTO_GLOBAL_OE On
+set_global_assignment -name AUTO_GLOBAL_REGISTER_CONTROLS On
+set_global_assignment -name FITTER_EARLY_TIMING_ESTIMATE_MODE Realistic
+set_global_assignment -name STRATIXGX_ALLOW_GIGE_UNDER_FULL_DATARATE_RANGE Off
+set_global_assignment -name STRATIXGX_ALLOW_RX_CORECLK_FROM_NON_RX_CLKOUT_SOURCE_IN_DOUBLE_DATA_WIDTH_MODE Off
+set_global_assignment -name STRATIXGX_ALLOW_GIGE_IN_DOUBLE_DATA_WIDTH_MODE Off
+set_global_assignment -name STRATIXGX_ALLOW_PARALLEL_LOOPBACK_IN_DOUBLE_DATA_WIDTH_MODE Off
+set_global_assignment -name STRATIXGX_ALLOW_XAUI_IN_SINGLE_DATA_WIDTH_MODE Off
+set_global_assignment -name STRATIXGX_ALLOW_XAUI_WITH_CORECLK_SELECTED_AT_RATE_MATCHER Off
+set_global_assignment -name STRATIXGX_ALLOW_XAUI_WITH_RX_CORECLK_FROM_NON_TXPLL_SOURCE Off
+set_global_assignment -name STRATIXGX_ALLOW_GIGE_WITH_CORECLK_SELECTED_AT_RATE_MATCHER Off
+set_global_assignment -name STRATIXGX_ALLOW_GIGE_WITHOUT_8B10B Off
+set_global_assignment -name STRATIXGX_ALLOW_GIGE_WITH_RX_CORECLK_FROM_NON_TXPLL_SOURCE Off
+set_global_assignment -name STRATIXGX_ALLOW_POST8B10B_LOOPBACK Off
+set_global_assignment -name STRATIXGX_ALLOW_REVERSE_PARALLEL_LOOPBACK Off
+set_global_assignment -name STRATIXGX_ALLOW_USE_OF_GXB_COUPLED_IOS Off
+set_global_assignment -name GENERATE_GXB_RECONFIG_MIF Off
+set_global_assignment -name GENERATE_GXB_RECONFIG_MIF_WITH_PLL Off
+set_global_assignment -name RESERVE_ALL_UNUSED_PINS_WEAK_PULLUP "As input tri-stated with weak pull-up"
+set_global_assignment -name ENABLE_HOLD_BACK_OFF On
+set_global_assignment -name CONFIGURATION_VCCIO_LEVEL Auto
+set_global_assignment -name FORCE_CONFIGURATION_VCCIO Off
+set_global_assignment -name SYNCHRONIZER_IDENTIFICATION Off
+set_global_assignment -name ENABLE_BENEFICIAL_SKEW_OPTIMIZATION On
+set_global_assignment -name OPTIMIZE_FOR_METASTABILITY On
+set_global_assignment -name CRC_ERROR_OPEN_DRAIN On -family "Arria V"
+set_global_assignment -name CRC_ERROR_OPEN_DRAIN Off -family "MAX 10"
+set_global_assignment -name CRC_ERROR_OPEN_DRAIN Off -family "Cyclone IV E"
+set_global_assignment -name CRC_ERROR_OPEN_DRAIN On -family "Arria 10"
+set_global_assignment -name CRC_ERROR_OPEN_DRAIN On -family "Stratix V"
+set_global_assignment -name CRC_ERROR_OPEN_DRAIN On -family "Arria V GZ"
+set_global_assignment -name CRC_ERROR_OPEN_DRAIN On -family "Cyclone V"
+set_global_assignment -name MAX_GLOBAL_CLOCKS_ALLOWED "-1 (Unlimited)"
+set_global_assignment -name MAX_REGIONAL_CLOCKS_ALLOWED "-1 (Unlimited)"
+set_global_assignment -name MAX_PERIPHERY_CLOCKS_ALLOWED "-1 (Unlimited)"
+set_global_assignment -name MAX_CLOCKS_ALLOWED "-1 (Unlimited)"
+set_global_assignment -name ACTIVE_SERIAL_CLOCK FREQ_100MHz -family "Arria 10"
+set_global_assignment -name ACTIVE_SERIAL_CLOCK FREQ_100MHz -family "Arria V"
+set_global_assignment -name ACTIVE_SERIAL_CLOCK FREQ_100MHz -family "Stratix V"
+set_global_assignment -name ACTIVE_SERIAL_CLOCK FREQ_40MHz -family "Cyclone IV GX"
+set_global_assignment -name ACTIVE_SERIAL_CLOCK FREQ_100MHz -family "Arria V GZ"
+set_global_assignment -name ACTIVE_SERIAL_CLOCK FREQ_100MHz -family "Cyclone V"
+set_global_assignment -name ACTIVE_SERIAL_CLOCK FREQ_40MHz -family "Arria II GX"
+set_global_assignment -name M144K_BLOCK_READ_CLOCK_DUTY_CYCLE_DEPENDENCY Off
+set_global_assignment -name STRATIXIII_MRAM_COMPATIBILITY On
+set_global_assignment -name FORCE_FITTER_TO_AVOID_PERIPHERY_PLACEMENT_WARNINGS Off
+set_global_assignment -name AUTO_C3_M9K_BIT_SKIP Off
+set_global_assignment -name PR_DONE_OPEN_DRAIN On
+set_global_assignment -name NCEO_OPEN_DRAIN On
+set_global_assignment -name ENABLE_CRC_ERROR_PIN Off
+set_global_assignment -name ENABLE_PR_PINS Off
+set_global_assignment -name PR_PINS_OPEN_DRAIN Off
+set_global_assignment -name CLAMPING_DIODE Off
+set_global_assignment -name TRI_STATE_SPI_PINS Off
+set_global_assignment -name UNUSED_TSD_PINS_GND Off
+set_global_assignment -name IMPLEMENT_MLAB_IN_16_BIT_DEEP_MODE Off
+set_global_assignment -name FORM_DDR_CLUSTERING_CLIQUE Off
+set_global_assignment -name ALM_REGISTER_PACKING_EFFORT Medium
+set_global_assignment -name ADVANCED_PHYSICAL_OPTIMIZATION On -family "Arria V"
+set_global_assignment -name ADVANCED_PHYSICAL_OPTIMIZATION Off -family "Stratix IV"
+set_global_assignment -name ADVANCED_PHYSICAL_OPTIMIZATION On -family "Arria 10"
+set_global_assignment -name ADVANCED_PHYSICAL_OPTIMIZATION On -family "Stratix V"
+set_global_assignment -name ADVANCED_PHYSICAL_OPTIMIZATION On -family "Arria V GZ"
+set_global_assignment -name ADVANCED_PHYSICAL_OPTIMIZATION On -family "Cyclone V"
+set_global_assignment -name EDA_SIMULATION_TOOL "<None>"
+set_global_assignment -name EDA_TIMING_ANALYSIS_TOOL "<None>"
+set_global_assignment -name EDA_BOARD_DESIGN_TIMING_TOOL "<None>"
+set_global_assignment -name EDA_BOARD_DESIGN_SYMBOL_TOOL "<None>"
+set_global_assignment -name EDA_BOARD_DESIGN_SIGNAL_INTEGRITY_TOOL "<None>"
+set_global_assignment -name EDA_BOARD_DESIGN_BOUNDARY_SCAN_TOOL "<None>"
+set_global_assignment -name EDA_BOARD_DESIGN_TOOL "<None>"
+set_global_assignment -name EDA_FORMAL_VERIFICATION_TOOL "<None>"
+set_global_assignment -name EDA_RESYNTHESIS_TOOL "<None>"
+set_global_assignment -name ON_CHIP_BITSTREAM_DECOMPRESSION On
+set_global_assignment -name COMPRESSION_MODE Off
+set_global_assignment -name CLOCK_SOURCE Internal
+set_global_assignment -name CONFIGURATION_CLOCK_FREQUENCY "10 MHz"
+set_global_assignment -name CONFIGURATION_CLOCK_DIVISOR 1
+set_global_assignment -name ENABLE_LOW_VOLTAGE_MODE_ON_CONFIG_DEVICE On
+set_global_assignment -name FLEX6K_ENABLE_LOW_VOLTAGE_MODE_ON_CONFIG_DEVICE Off
+set_global_assignment -name FLEX10K_ENABLE_LOW_VOLTAGE_MODE_ON_CONFIG_DEVICE On
+set_global_assignment -name MAX7000S_JTAG_USER_CODE FFFF
+set_global_assignment -name STRATIX_JTAG_USER_CODE FFFFFFFF
+set_global_assignment -name APEX20K_JTAG_USER_CODE FFFFFFFF
+set_global_assignment -name MERCURY_JTAG_USER_CODE FFFFFFFF
+set_global_assignment -name FLEX10K_JTAG_USER_CODE 7F
+set_global_assignment -name MAX7000_JTAG_USER_CODE FFFFFFFF
+set_global_assignment -name MAX7000_USE_CHECKSUM_AS_USERCODE Off
+set_global_assignment -name USE_CHECKSUM_AS_USERCODE On
+set_global_assignment -name SECURITY_BIT Off
+set_global_assignment -name USE_CONFIGURATION_DEVICE On -family "MAX 10"
+set_global_assignment -name USE_CONFIGURATION_DEVICE Off -family "Cyclone IV E"
+set_global_assignment -name USE_CONFIGURATION_DEVICE Off -family "Stratix IV"
+set_global_assignment -name USE_CONFIGURATION_DEVICE On -family "MAX V"
+set_global_assignment -name USE_CONFIGURATION_DEVICE On -family "MAX II"
+set_global_assignment -name USE_CONFIGURATION_DEVICE Off -family "Arria II GX"
+set_global_assignment -name USE_CONFIGURATION_DEVICE Off -family "Arria II GZ"
+set_global_assignment -name USE_CONFIGURATION_DEVICE Off -family "Cyclone IV GX"
+set_global_assignment -name CYCLONEIII_CONFIGURATION_DEVICE Auto
+set_global_assignment -name STRATIXII_CONFIGURATION_DEVICE Auto
+set_global_assignment -name APEX20K_CONFIGURATION_DEVICE Auto
+set_global_assignment -name MERCURY_CONFIGURATION_DEVICE Auto
+set_global_assignment -name FLEX6K_CONFIGURATION_DEVICE Auto
+set_global_assignment -name FLEX10K_CONFIGURATION_DEVICE Auto
+set_global_assignment -name CYCLONE_CONFIGURATION_DEVICE Auto
+set_global_assignment -name STRATIX_CONFIGURATION_DEVICE Auto
+set_global_assignment -name APEX20K_CONFIG_DEVICE_JTAG_USER_CODE FFFFFFFF
+set_global_assignment -name STRATIX_CONFIG_DEVICE_JTAG_USER_CODE FFFFFFFF
+set_global_assignment -name MERCURY_CONFIG_DEVICE_JTAG_USER_CODE FFFFFFFF
+set_global_assignment -name FLEX10K_CONFIG_DEVICE_JTAG_USER_CODE FFFFFFFF
+set_global_assignment -name EPROM_USE_CHECKSUM_AS_USERCODE Off
+set_global_assignment -name AUTO_INCREMENT_CONFIG_DEVICE_JTAG_USER_CODE On
+set_global_assignment -name DISABLE_NCS_AND_OE_PULLUPS_ON_CONFIG_DEVICE Off
+set_global_assignment -name GENERATE_TTF_FILE Off
+set_global_assignment -name GENERATE_RBF_FILE Off
+set_global_assignment -name GENERATE_HEX_FILE Off
+set_global_assignment -name HEXOUT_FILE_START_ADDRESS 0
+set_global_assignment -name HEXOUT_FILE_COUNT_DIRECTION Up
+set_global_assignment -name RESERVE_ALL_UNUSED_PINS_NO_OUTPUT_GND "As output driving an unspecified signal"
+set_global_assignment -name RELEASE_CLEARS_BEFORE_TRI_STATES Off
+set_global_assignment -name AUTO_RESTART_CONFIGURATION On
+set_global_assignment -name HARDCOPYII_POWER_ON_EXTRA_DELAY Off
+set_global_assignment -name STRATIXII_MRAM_COMPATIBILITY Off
+set_global_assignment -name CYCLONEII_M4K_COMPATIBILITY On
+set_global_assignment -name ENABLE_OCT_DONE Off -family "Arria V"
+set_global_assignment -name ENABLE_OCT_DONE On -family "MAX 10"
+set_global_assignment -name ENABLE_OCT_DONE Off -family "Cyclone IV E"
+set_global_assignment -name ENABLE_OCT_DONE Off -family "Arria 10"
+set_global_assignment -name ENABLE_OCT_DONE Off -family "Stratix V"
+set_global_assignment -name ENABLE_OCT_DONE Off -family "Arria V GZ"
+set_global_assignment -name ENABLE_OCT_DONE Off -family "Arria II GX"
+set_global_assignment -name ENABLE_OCT_DONE Off -family "Cyclone IV GX"
+set_global_assignment -name ENABLE_OCT_DONE Off -family "Cyclone V"
+set_global_assignment -name USE_CHECKERED_PATTERN_AS_UNINITIALIZED_RAM_CONTENT OFF
+set_global_assignment -name ARRIAIIGX_RX_CDR_LOCKUP_FIX_OVERRIDE Off
+set_global_assignment -name ENABLE_AUTONOMOUS_PCIE_HIP Off
+set_global_assignment -name ENABLE_ADV_SEU_DETECTION Off
+set_global_assignment -name POR_SCHEME "Instant ON"
+set_global_assignment -name EN_USER_IO_WEAK_PULLUP On
+set_global_assignment -name EN_SPI_IO_WEAK_PULLUP On
+set_global_assignment -name POF_VERIFY_PROTECT Off
+set_global_assignment -name ENABLE_SPI_MODE_CHECK Off
+set_global_assignment -name FORCE_SSMCLK_TO_ISMCLK On
+set_global_assignment -name FALLBACK_TO_EXTERNAL_FLASH Off
+set_global_assignment -name EXTERNAL_FLASH_FALLBACK_ADDRESS 0
+set_global_assignment -name START_TIME 0ns
+set_global_assignment -name SIMULATION_MODE TIMING
+set_global_assignment -name AUTO_USE_SIMULATION_PDB_NETLIST Off
+set_global_assignment -name ADD_DEFAULT_PINS_TO_SIMULATION_OUTPUT_WAVEFORMS On
+set_global_assignment -name SETUP_HOLD_DETECTION Off
+set_global_assignment -name SETUP_HOLD_DETECTION_INPUT_REGISTERS_BIDIR_PINS_DISABLED Off
+set_global_assignment -name CHECK_OUTPUTS Off
+set_global_assignment -name SIMULATION_COVERAGE On
+set_global_assignment -name SIMULATION_COMPLETE_COVERAGE_REPORT_PANEL On
+set_global_assignment -name SIMULATION_MISSING_1_VALUE_COVERAGE_REPORT_PANEL On
+set_global_assignment -name SIMULATION_MISSING_0_VALUE_COVERAGE_REPORT_PANEL On
+set_global_assignment -name GLITCH_DETECTION Off
+set_global_assignment -name GLITCH_INTERVAL 1ns
+set_global_assignment -name SIMULATOR_GENERATE_SIGNAL_ACTIVITY_FILE Off
+set_global_assignment -name SIMULATION_WITH_GLITCH_FILTERING_WHEN_GENERATING_SAF On
+set_global_assignment -name SIMULATION_BUS_CHANNEL_GROUPING Off
+set_global_assignment -name SIMULATION_VDB_RESULT_FLUSH On
+set_global_assignment -name VECTOR_COMPARE_TRIGGER_MODE INPUT_EDGE
+set_global_assignment -name SIMULATION_NETLIST_VIEWER Off
+set_global_assignment -name SIMULATION_INTERCONNECT_DELAY_MODEL_TYPE TRANSPORT
+set_global_assignment -name SIMULATION_CELL_DELAY_MODEL_TYPE TRANSPORT
+set_global_assignment -name SIMULATOR_GENERATE_POWERPLAY_VCD_FILE Off
+set_global_assignment -name SIMULATOR_PVT_TIMING_MODEL_TYPE AUTO
+set_global_assignment -name SIMULATION_WITH_AUTO_GLITCH_FILTERING AUTO
+set_global_assignment -name DRC_TOP_FANOUT 50
+set_global_assignment -name DRC_FANOUT_EXCEEDING 30
+set_global_assignment -name DRC_GATED_CLOCK_FEED 30
+set_global_assignment -name HARDCOPY_FLOW_AUTOMATION MIGRATION_ONLY
+set_global_assignment -name ENABLE_DRC_SETTINGS Off
+set_global_assignment -name CLK_RULE_CLKNET_CLKSPINES_THRESHOLD 25
+set_global_assignment -name DRC_DETAIL_MESSAGE_LIMIT 10
+set_global_assignment -name DRC_VIOLATION_MESSAGE_LIMIT 30
+set_global_assignment -name DRC_DEADLOCK_STATE_LIMIT 2
+set_global_assignment -name MERGE_HEX_FILE Off
+set_global_assignment -name GENERATE_SVF_FILE Off
+set_global_assignment -name GENERATE_ISC_FILE Off
+set_global_assignment -name GENERATE_JAM_FILE Off
+set_global_assignment -name GENERATE_JBC_FILE Off
+set_global_assignment -name GENERATE_JBC_FILE_COMPRESSED On
+set_global_assignment -name GENERATE_CONFIG_SVF_FILE Off
+set_global_assignment -name GENERATE_CONFIG_ISC_FILE Off
+set_global_assignment -name GENERATE_CONFIG_JAM_FILE Off
+set_global_assignment -name GENERATE_CONFIG_JBC_FILE Off
+set_global_assignment -name GENERATE_CONFIG_JBC_FILE_COMPRESSED On
+set_global_assignment -name GENERATE_CONFIG_HEXOUT_FILE Off
+set_global_assignment -name ISP_CLAMP_STATE_DEFAULT "Tri-state"
+set_global_assignment -name HPS_EARLY_IO_RELEASE Off
+set_global_assignment -name SIGNALPROBE_ALLOW_OVERUSE Off
+set_global_assignment -name SIGNALPROBE_DURING_NORMAL_COMPILATION Off
+set_global_assignment -name POWER_DEFAULT_TOGGLE_RATE 12.5%
+set_global_assignment -name POWER_DEFAULT_INPUT_IO_TOGGLE_RATE 12.5%
+set_global_assignment -name POWER_USE_PVA On
+set_global_assignment -name POWER_USE_INPUT_FILE "No File"
+set_global_assignment -name POWER_USE_INPUT_FILES Off
+set_global_assignment -name POWER_VCD_FILTER_GLITCHES On
+set_global_assignment -name POWER_REPORT_SIGNAL_ACTIVITY Off
+set_global_assignment -name POWER_REPORT_POWER_DISSIPATION Off
+set_global_assignment -name POWER_USE_DEVICE_CHARACTERISTICS TYPICAL
+set_global_assignment -name POWER_AUTO_COMPUTE_TJ On
+set_global_assignment -name POWER_TJ_VALUE 25
+set_global_assignment -name POWER_USE_TA_VALUE 25
+set_global_assignment -name POWER_USE_CUSTOM_COOLING_SOLUTION Off
+set_global_assignment -name POWER_BOARD_TEMPERATURE 25
+set_global_assignment -name POWER_HPS_ENABLE Off
+set_global_assignment -name POWER_HPS_PROC_FREQ 0.0
+set_global_assignment -name ENABLE_SMART_VOLTAGE_ID Off
+set_global_assignment -name IGNORE_PARTITIONS Off
+set_global_assignment -name AUTO_EXPORT_INCREMENTAL_COMPILATION Off
+set_global_assignment -name RAPID_RECOMPILE_ASSIGNMENT_CHECKING On
+set_global_assignment -name OUTPUT_IO_TIMING_ENDPOINT "Near End"
+set_global_assignment -name RTLV_REMOVE_FANOUT_FREE_REGISTERS On
+set_global_assignment -name RTLV_SIMPLIFIED_LOGIC On
+set_global_assignment -name RTLV_GROUP_RELATED_NODES On
+set_global_assignment -name RTLV_GROUP_COMB_LOGIC_IN_CLOUD Off
+set_global_assignment -name RTLV_GROUP_COMB_LOGIC_IN_CLOUD_TMV Off
+set_global_assignment -name RTLV_GROUP_RELATED_NODES_TMV On
+set_global_assignment -name EQC_CONSTANT_DFF_DETECTION On
+set_global_assignment -name EQC_DUPLICATE_DFF_DETECTION On
+set_global_assignment -name EQC_BBOX_MERGE On
+set_global_assignment -name EQC_LVDS_MERGE On
+set_global_assignment -name EQC_RAM_UNMERGING On
+set_global_assignment -name EQC_DFF_SS_EMULATION On
+set_global_assignment -name EQC_RAM_REGISTER_UNPACK On
+set_global_assignment -name EQC_MAC_REGISTER_UNPACK On
+set_global_assignment -name EQC_SET_PARTITION_BB_TO_VCC_GND On
+set_global_assignment -name EQC_STRUCTURE_MATCHING On
+set_global_assignment -name EQC_AUTO_BREAK_CONE On
+set_global_assignment -name EQC_POWER_UP_COMPARE Off
+set_global_assignment -name EQC_AUTO_COMP_LOOP_CUT On
+set_global_assignment -name EQC_AUTO_INVERSION On
+set_global_assignment -name EQC_AUTO_TERMINATE On
+set_global_assignment -name EQC_SUB_CONE_REPORT Off
+set_global_assignment -name EQC_RENAMING_RULES On
+set_global_assignment -name EQC_PARAMETER_CHECK On
+set_global_assignment -name EQC_AUTO_PORTSWAP On
+set_global_assignment -name EQC_DETECT_DONT_CARES On
+set_global_assignment -name EQC_SHOW_ALL_MAPPED_POINTS Off
+set_global_assignment -name EDA_INPUT_GND_NAME GND -section_id ?
+set_global_assignment -name EDA_INPUT_VCC_NAME VCC -section_id ?
+set_global_assignment -name EDA_INPUT_DATA_FORMAT NONE -section_id ?
+set_global_assignment -name EDA_SHOW_LMF_MAPPING_MESSAGES Off -section_id ?
+set_global_assignment -name EDA_RUN_TOOL_AUTOMATICALLY Off -section_id ?
+set_global_assignment -name RESYNTHESIS_RETIMING FULL -section_id ?
+set_global_assignment -name RESYNTHESIS_OPTIMIZATION_EFFORT Normal -section_id ?
+set_global_assignment -name RESYNTHESIS_PHYSICAL_SYNTHESIS Normal -section_id ?
+set_global_assignment -name USE_GENERATED_PHYSICAL_CONSTRAINTS On -section_id ?
+set_global_assignment -name VCCPD_VOLTAGE 3.3V -section_id ?
+set_global_assignment -name EDA_USER_COMPILED_SIMULATION_LIBRARY_DIRECTORY "<None>" -section_id ?
+set_global_assignment -name EDA_LAUNCH_CMD_LINE_TOOL Off -section_id ?
+set_global_assignment -name EDA_ENABLE_IPUTF_MODE On -section_id ?
+set_global_assignment -name EDA_NATIVELINK_PORTABLE_FILE_PATHS Off -section_id ?
+set_global_assignment -name EDA_NATIVELINK_GENERATE_SCRIPT_ONLY Off -section_id ?
+set_global_assignment -name EDA_WAIT_FOR_GUI_TOOL_COMPLETION Off -section_id ?
+set_global_assignment -name EDA_TRUNCATE_LONG_HIERARCHY_PATHS Off -section_id ?
+set_global_assignment -name EDA_FLATTEN_BUSES Off -section_id ?
+set_global_assignment -name EDA_MAP_ILLEGAL_CHARACTERS Off -section_id ?
+set_global_assignment -name EDA_GENERATE_TIMING_CLOSURE_DATA Off -section_id ?
+set_global_assignment -name EDA_GENERATE_POWER_INPUT_FILE Off -section_id ?
+set_global_assignment -name EDA_TEST_BENCH_ENABLE_STATUS NOT_USED -section_id ?
+set_global_assignment -name EDA_RTL_SIM_MODE NOT_USED -section_id ?
+set_global_assignment -name EDA_MAINTAIN_DESIGN_HIERARCHY OFF -section_id ?
+set_global_assignment -name EDA_GENERATE_FUNCTIONAL_NETLIST Off -section_id ?
+set_global_assignment -name EDA_WRITE_DEVICE_CONTROL_PORTS Off -section_id ?
+set_global_assignment -name EDA_SIMULATION_VCD_OUTPUT_TCL_FILE Off -section_id ?
+set_global_assignment -name EDA_SIMULATION_VCD_OUTPUT_SIGNALS_TO_TCL_FILE "All Except Combinational Logic Element Outputs" -section_id ?
+set_global_assignment -name EDA_ENABLE_GLITCH_FILTERING Off -section_id ?
+set_global_assignment -name EDA_WRITE_NODES_FOR_POWER_ESTIMATION OFF -section_id ?
+set_global_assignment -name EDA_SETUP_HOLD_DETECTION_INPUT_REGISTERS_BIDIR_PINS_DISABLED Off -section_id ?
+set_global_assignment -name EDA_WRITER_DONT_WRITE_TOP_ENTITY Off -section_id ?
+set_global_assignment -name EDA_VHDL_ARCH_NAME structure -section_id ?
+set_global_assignment -name EDA_IBIS_MODEL_SELECTOR Off -section_id ?
+set_global_assignment -name EDA_IBIS_MUTUAL_COUPLING Off -section_id ?
+set_global_assignment -name EDA_FORMAL_VERIFICATION_ALLOW_RETIMING Off -section_id ?
+set_global_assignment -name EDA_BOARD_BOUNDARY_SCAN_OPERATION PRE_CONFIG -section_id ?
+set_global_assignment -name EDA_GENERATE_RTL_SIMULATION_COMMAND_SCRIPT Off -section_id ?
+set_global_assignment -name EDA_GENERATE_GATE_LEVEL_SIMULATION_COMMAND_SCRIPT Off -section_id ?
+set_global_assignment -name EDA_IBIS_SPECIFICATION_VERSION 4p1 -section_id ?
+set_global_assignment -name SIM_VECTOR_COMPARED_CLOCK_OFFSET 0ns -section_id ?
+set_global_assignment -name SIM_VECTOR_COMPARED_CLOCK_DUTY_CYCLE 50 -section_id ?
+set_global_assignment -name APEX20K_CLIQUE_TYPE LAB -section_id ? -entity ?
+set_global_assignment -name MAX7K_CLIQUE_TYPE LAB -section_id ? -entity ?
+set_global_assignment -name MERCURY_CLIQUE_TYPE LAB -section_id ? -entity ?
+set_global_assignment -name FLEX6K_CLIQUE_TYPE LAB -section_id ? -entity ?
+set_global_assignment -name FLEX10K_CLIQUE_TYPE LAB -section_id ? -entity ?
+set_global_assignment -name PARTITION_PRESERVE_HIGH_SPEED_TILES On -section_id ? -entity ?
+set_global_assignment -name PARTITION_IGNORE_SOURCE_FILE_CHANGES Off -section_id ? -entity ?
+set_global_assignment -name PARTITION_ALWAYS_USE_QXP_NETLIST Off -section_id ? -entity ?
+set_global_assignment -name PARTITION_IMPORT_ASSIGNMENTS On -section_id ? -entity ?
+set_global_assignment -name PARTITION_IMPORT_EXISTING_ASSIGNMENTS REPLACE_CONFLICTING -section_id ? -entity ?
+set_global_assignment -name PARTITION_IMPORT_EXISTING_LOGICLOCK_REGIONS UPDATE_CONFLICTING -section_id ? -entity ?
+set_global_assignment -name PARTITION_IMPORT_PROMOTE_ASSIGNMENTS On -section_id ? -entity ?
+set_global_assignment -name ALLOW_MULTIPLE_PERSONAS Off -section_id ? -entity ?
+set_global_assignment -name PARTITION_ASD_REGION_ID 1 -section_id ? -entity ?
+set_global_assignment -name CROSS_BOUNDARY_OPTIMIZATIONS Off -section_id ? -entity ?
+set_global_assignment -name PROPAGATE_CONSTANTS_ON_INPUTS On -section_id ? -entity ?
+set_global_assignment -name PROPAGATE_INVERSIONS_ON_INPUTS On -section_id ? -entity ?
+set_global_assignment -name REMOVE_LOGIC_ON_UNCONNECTED_OUTPUTS On -section_id ? -entity ?
+set_global_assignment -name MERGE_EQUIVALENT_INPUTS On -section_id ? -entity ?
+set_global_assignment -name MERGE_EQUIVALENT_BIDIRS On -section_id ? -entity ?
+set_global_assignment -name ABSORB_PATHS_FROM_OUTPUTS_TO_INPUTS On -section_id ? -entity ?
+set_global_assignment -name PARTITION_ENABLE_STRICT_PRESERVATION Off -section_id ? -entity ?

+ 35 - 0
logic/boot_ip.v

@@ -0,0 +1,35 @@
+module boot_ip (
+  input         sys_clock,
+  input         bus_clock,
+  input         resetn,
+  input         stop,
+  input  [1:0]  mem_ahb_htrans,
+  input         mem_ahb_hready,
+  input         mem_ahb_hwrite,
+  input  [31:0] mem_ahb_haddr,
+  input  [2:0]  mem_ahb_hsize,
+  input  [2:0]  mem_ahb_hburst,
+  input  [31:0] mem_ahb_hwdata,
+  output tri1   mem_ahb_hreadyout,
+  output        mem_ahb_hresp,
+  output [31:0] mem_ahb_hrdata,
+  output        slave_ahb_hsel,
+  output tri1   slave_ahb_hready,
+  input         slave_ahb_hreadyout,
+  output [1:0]  slave_ahb_htrans,
+  output [2:0]  slave_ahb_hsize,
+  output [2:0]  slave_ahb_hburst,
+  output        slave_ahb_hwrite,
+  output [31:0] slave_ahb_haddr,
+  output [31:0] slave_ahb_hwdata,
+  input         slave_ahb_hresp,
+  input  [31:0] slave_ahb_hrdata,
+  output [3:0]  ext_dma_DMACBREQ,
+  output [3:0]  ext_dma_DMACLBREQ,
+  output [3:0]  ext_dma_DMACSREQ,
+  output [3:0]  ext_dma_DMACLSREQ,
+  input  [3:0]  ext_dma_DMACCLR,
+  input  [3:0]  ext_dma_DMACTC,
+  output [3:0]  local_int
+);
+endmodule

+ 1536 - 0
logic/boot_routed.v

@@ -0,0 +1,1536 @@
+`timescale 1 ps/ 1 ps
+
+module top(
+	PIN_1,
+	PIN_2,
+	PIN_3,
+	PIN_68,
+	PIN_69,
+	PIN_88,
+	PIN_91,
+	PIN_92,
+	PIN_95,
+	PIN_96,
+	PIN_97,
+	PIN_HSE,
+	PIN_HSI,
+	PIN_OSC);
+inout	PIN_1;
+inout	PIN_2;
+inout	PIN_3;
+output	PIN_68;
+input	PIN_69;
+inout	PIN_88;
+inout	PIN_91;
+inout	PIN_92;
+inout	PIN_95;
+inout	PIN_96;
+inout	PIN_97;
+input	PIN_HSE;
+input	PIN_HSI;
+input	PIN_OSC;
+
+//wire	gnd;
+//wire	vcc;
+wire	\PIN_1~input_o ;
+wire	\PIN_2~input_o ;
+wire	\PIN_3~input_o ;
+wire	\PIN_69~input_o ;
+wire	\PIN_88~input_o ;
+wire	\PIN_91~input_o ;
+wire	\PIN_92~input_o ;
+wire	\PIN_95~input_o ;
+wire	\PIN_96~input_o ;
+wire	\PIN_97~input_o ;
+wire	\PIN_HSE~input_o ;
+wire	\PIN_HSI~input_o ;
+wire	\PIN_OSC~input_o ;
+wire	\PLL_ENABLE~clkctrl_outclk ;
+wire	\PLL_ENABLE~clkctrl_outclk__AsyncReset_X47_Y1_SIG ;
+wire	\PLL_ENABLE~combout ;
+wire	\PLL_LOCK~combout ;
+wire	\auto_generated_inst.hbo_13_a07d11f4c42b3d12_bp ;
+wire	\auto_generated_inst.hbo_13_a07d11f4c42b3d12_bp_X47_Y1_SIG_VCC ;
+wire	\auto_generated_inst.hbo_22_f9ff3d300b43c0f2_bp ;
+tri1	devclrn;
+tri1	devoe;
+tri1	devpor;
+wire	[3:0] ext_dma_DMACBREQ;
+//wire	ext_dma_DMACBREQ[0];
+//wire	ext_dma_DMACBREQ[1];
+//wire	ext_dma_DMACBREQ[2];
+//wire	ext_dma_DMACBREQ[3];
+wire	[3:0] ext_dma_DMACLBREQ;
+//wire	ext_dma_DMACLBREQ[0];
+//wire	ext_dma_DMACLBREQ[1];
+//wire	ext_dma_DMACLBREQ[2];
+//wire	ext_dma_DMACLBREQ[3];
+wire	[3:0] ext_dma_DMACLSREQ;
+//wire	ext_dma_DMACLSREQ[0];
+//wire	ext_dma_DMACLSREQ[1];
+//wire	ext_dma_DMACLSREQ[2];
+//wire	ext_dma_DMACLSREQ[3];
+wire	[3:0] ext_dma_DMACSREQ;
+//wire	ext_dma_DMACSREQ[0];
+//wire	ext_dma_DMACSREQ[1];
+//wire	ext_dma_DMACSREQ[2];
+//wire	ext_dma_DMACSREQ[3];
+wire	\gclksw_inst|gclk_switch__alta_gclksw__clkout ;
+wire	[7:0] gpio0_io_in;
+//wire	gpio0_io_in[0];
+//wire	gpio0_io_in[1];
+//wire	gpio0_io_in[2];
+//wire	gpio0_io_in[3];
+//wire	gpio0_io_in[4];
+//wire	gpio0_io_in[5];
+//wire	gpio0_io_in[6];
+//wire	gpio0_io_in[7];
+wire	[7:0] gpio1_io_in;
+//wire	gpio1_io_in[0];
+//wire	gpio1_io_in[1];
+//wire	gpio1_io_in[2];
+//wire	gpio1_io_in[3];
+//wire	gpio1_io_in[4];
+//wire	gpio1_io_in[5];
+//wire	gpio1_io_in[6];
+//wire	gpio1_io_in[7];
+wire	[7:0] gpio1_io_out_data;
+//wire	gpio1_io_out_data[0];
+//wire	gpio1_io_out_data[1];
+//wire	gpio1_io_out_data[2];
+//wire	gpio1_io_out_data[3];
+//wire	gpio1_io_out_data[4];
+//wire	gpio1_io_out_data[5];
+//wire	gpio1_io_out_data[6];
+//wire	gpio1_io_out_data[7];
+wire	[7:0] gpio1_io_out_en;
+//wire	gpio1_io_out_en[0];
+//wire	gpio1_io_out_en[1];
+//wire	gpio1_io_out_en[2];
+//wire	gpio1_io_out_en[3];
+//wire	gpio1_io_out_en[4];
+//wire	gpio1_io_out_en[5];
+//wire	gpio1_io_out_en[6];
+//wire	gpio1_io_out_en[7];
+wire	[7:0] gpio2_io_in;
+//wire	gpio2_io_in[0];
+//wire	gpio2_io_in[1];
+//wire	gpio2_io_in[2];
+//wire	gpio2_io_in[3];
+//wire	gpio2_io_in[4];
+//wire	gpio2_io_in[5];
+//wire	gpio2_io_in[6];
+//wire	gpio2_io_in[7];
+wire	[7:0] gpio2_io_out_data;
+//wire	gpio2_io_out_data[0];
+//wire	gpio2_io_out_data[1];
+//wire	gpio2_io_out_data[2];
+//wire	gpio2_io_out_data[3];
+//wire	gpio2_io_out_data[4];
+//wire	gpio2_io_out_data[5];
+//wire	gpio2_io_out_data[6];
+//wire	gpio2_io_out_data[7];
+wire	[7:0] gpio2_io_out_en;
+//wire	gpio2_io_out_en[0];
+//wire	gpio2_io_out_en[1];
+//wire	gpio2_io_out_en[2];
+//wire	gpio2_io_out_en[3];
+//wire	gpio2_io_out_en[4];
+//wire	gpio2_io_out_en[5];
+//wire	gpio2_io_out_en[6];
+//wire	gpio2_io_out_en[7];
+wire	[7:0] gpio3_io_in;
+//wire	gpio3_io_in[0];
+//wire	gpio3_io_in[1];
+//wire	gpio3_io_in[2];
+//wire	gpio3_io_in[3];
+//wire	gpio3_io_in[4];
+//wire	gpio3_io_in[5];
+//wire	gpio3_io_in[6];
+//wire	gpio3_io_in[7];
+wire	[7:0] gpio4_io_in;
+//wire	gpio4_io_in[0];
+//wire	gpio4_io_in[1];
+//wire	gpio4_io_in[2];
+//wire	gpio4_io_in[3];
+//wire	gpio4_io_in[4];
+//wire	gpio4_io_in[5];
+//wire	gpio4_io_in[6];
+//wire	gpio4_io_in[7];
+wire	[7:0] gpio5_io_in;
+//wire	gpio5_io_in[0];
+//wire	gpio5_io_in[1];
+//wire	gpio5_io_in[2];
+//wire	gpio5_io_in[3];
+//wire	gpio5_io_in[4];
+//wire	gpio5_io_in[5];
+//wire	gpio5_io_in[6];
+//wire	gpio5_io_in[7];
+wire	[7:0] gpio6_io_in;
+//wire	gpio6_io_in[0];
+//wire	gpio6_io_in[1];
+//wire	gpio6_io_in[2];
+//wire	gpio6_io_in[3];
+//wire	gpio6_io_in[4];
+//wire	gpio6_io_in[5];
+//wire	gpio6_io_in[6];
+//wire	gpio6_io_in[7];
+wire	[7:0] gpio7_io_in;
+//wire	gpio7_io_in[0];
+//wire	gpio7_io_in[1];
+//wire	gpio7_io_in[2];
+//wire	gpio7_io_in[3];
+//wire	gpio7_io_in[4];
+//wire	gpio7_io_in[5];
+//wire	gpio7_io_in[6];
+//wire	gpio7_io_in[7];
+wire	[7:0] gpio7_io_out_data;
+//wire	gpio7_io_out_data[0];
+//wire	gpio7_io_out_data[1];
+//wire	gpio7_io_out_data[2];
+//wire	gpio7_io_out_data[3];
+//wire	gpio7_io_out_data[4];
+//wire	gpio7_io_out_data[5];
+//wire	gpio7_io_out_data[6];
+//wire	gpio7_io_out_data[7];
+wire	[7:0] gpio7_io_out_en;
+//wire	gpio7_io_out_en[0];
+//wire	gpio7_io_out_en[1];
+//wire	gpio7_io_out_en[2];
+//wire	gpio7_io_out_en[3];
+//wire	gpio7_io_out_en[4];
+//wire	gpio7_io_out_en[5];
+//wire	gpio7_io_out_en[6];
+//wire	gpio7_io_out_en[7];
+wire	[7:0] gpio8_io_in;
+//wire	gpio8_io_in[0];
+//wire	gpio8_io_in[1];
+//wire	gpio8_io_in[2];
+//wire	gpio8_io_in[3];
+//wire	gpio8_io_in[4];
+//wire	gpio8_io_in[5];
+//wire	gpio8_io_in[6];
+//wire	gpio8_io_in[7];
+wire	[7:0] gpio9_io_in;
+//wire	gpio9_io_in[0];
+//wire	gpio9_io_in[1];
+//wire	gpio9_io_in[2];
+//wire	gpio9_io_in[3];
+//wire	gpio9_io_in[4];
+//wire	gpio9_io_in[5];
+//wire	gpio9_io_in[6];
+//wire	gpio9_io_in[7];
+wire	hbi_274_0_9cb2c0024f9919c5_bp;
+wire	hbi_274_1_9cb2c0024f9919c5_bp;
+wire	[3:0] local_int;
+//wire	local_int[0];
+//wire	local_int[1];
+//wire	local_int[2];
+//wire	local_int[3];
+wire	[31:0] mem_ahb_hrdata;
+//wire	mem_ahb_hrdata[0];
+//wire	mem_ahb_hrdata[10];
+//wire	mem_ahb_hrdata[11];
+//wire	mem_ahb_hrdata[12];
+//wire	mem_ahb_hrdata[13];
+//wire	mem_ahb_hrdata[14];
+//wire	mem_ahb_hrdata[15];
+//wire	mem_ahb_hrdata[16];
+//wire	mem_ahb_hrdata[17];
+//wire	mem_ahb_hrdata[18];
+//wire	mem_ahb_hrdata[19];
+//wire	mem_ahb_hrdata[1];
+//wire	mem_ahb_hrdata[20];
+//wire	mem_ahb_hrdata[21];
+//wire	mem_ahb_hrdata[22];
+//wire	mem_ahb_hrdata[23];
+//wire	mem_ahb_hrdata[24];
+//wire	mem_ahb_hrdata[25];
+//wire	mem_ahb_hrdata[26];
+//wire	mem_ahb_hrdata[27];
+//wire	mem_ahb_hrdata[28];
+//wire	mem_ahb_hrdata[29];
+//wire	mem_ahb_hrdata[2];
+//wire	mem_ahb_hrdata[30];
+//wire	mem_ahb_hrdata[31];
+//wire	mem_ahb_hrdata[3];
+//wire	mem_ahb_hrdata[4];
+//wire	mem_ahb_hrdata[5];
+//wire	mem_ahb_hrdata[6];
+//wire	mem_ahb_hrdata[7];
+//wire	mem_ahb_hrdata[8];
+//wire	mem_ahb_hrdata[9];
+wire	\mem_ahb_hreadyout~combout ;
+wire	\mem_ahb_hresp~combout ;
+wire	[4:0] \pll_inst|auto_generated|clk ;
+//wire	\pll_inst|auto_generated|clk [0];
+//wire	\pll_inst|auto_generated|clk [1];
+//wire	\pll_inst|auto_generated|clk [2];
+//wire	\pll_inst|auto_generated|clk [3];
+//wire	\pll_inst|auto_generated|clk [4];
+wire	[4:0] \pll_inst|auto_generated|pll1_CLK_bus ;
+//wire	\pll_inst|auto_generated|pll1_CLK_bus [0];
+//wire	\pll_inst|auto_generated|pll1_CLK_bus [1];
+//wire	\pll_inst|auto_generated|pll1_CLK_bus [2];
+//wire	\pll_inst|auto_generated|pll1_CLK_bus [3];
+//wire	\pll_inst|auto_generated|pll1_CLK_bus [4];
+wire	\pll_inst|auto_generated|pll1~FBOUT ;
+wire	\pll_inst|auto_generated|pll_lock_sync~feeder_combout ;
+wire	\pll_inst|auto_generated|pll_lock_sync~q ;
+wire	\rv32.dmactive ;
+wire	\rv32.ext_dma_DMACCLR[0] ;
+wire	\rv32.ext_dma_DMACCLR[1] ;
+wire	\rv32.ext_dma_DMACCLR[2] ;
+wire	\rv32.ext_dma_DMACCLR[3] ;
+wire	\rv32.ext_dma_DMACTC[0] ;
+wire	\rv32.ext_dma_DMACTC[1] ;
+wire	\rv32.ext_dma_DMACTC[2] ;
+wire	\rv32.ext_dma_DMACTC[3] ;
+wire	\rv32.gpio0_io_out_data[0] ;
+wire	\rv32.gpio0_io_out_data[1] ;
+wire	\rv32.gpio0_io_out_data[2] ;
+wire	\rv32.gpio0_io_out_data[3] ;
+wire	\rv32.gpio0_io_out_data[4] ;
+wire	\rv32.gpio0_io_out_data[5] ;
+wire	\rv32.gpio0_io_out_data[6] ;
+wire	\rv32.gpio0_io_out_data[7] ;
+wire	\rv32.gpio0_io_out_en[0] ;
+wire	\rv32.gpio0_io_out_en[1] ;
+wire	\rv32.gpio0_io_out_en[2] ;
+wire	\rv32.gpio0_io_out_en[3] ;
+wire	\rv32.gpio0_io_out_en[4] ;
+wire	\rv32.gpio0_io_out_en[5] ;
+wire	\rv32.gpio0_io_out_en[6] ;
+wire	\rv32.gpio0_io_out_en[7] ;
+wire	\rv32.gpio1_io_out_data[0] ;
+wire	\rv32.gpio1_io_out_data[1] ;
+wire	\rv32.gpio1_io_out_data[2] ;
+wire	\rv32.gpio1_io_out_data[3] ;
+wire	\rv32.gpio1_io_out_data[4] ;
+wire	\rv32.gpio1_io_out_data[5] ;
+wire	\rv32.gpio1_io_out_data[6] ;
+wire	\rv32.gpio1_io_out_data[7] ;
+wire	\rv32.gpio1_io_out_en[0] ;
+wire	\rv32.gpio1_io_out_en[1] ;
+wire	\rv32.gpio1_io_out_en[2] ;
+wire	\rv32.gpio1_io_out_en[3] ;
+wire	\rv32.gpio1_io_out_en[4] ;
+wire	\rv32.gpio1_io_out_en[5] ;
+wire	\rv32.gpio1_io_out_en[6] ;
+wire	\rv32.gpio1_io_out_en[7] ;
+wire	\rv32.gpio2_io_out_data[0] ;
+wire	\rv32.gpio2_io_out_data[1] ;
+wire	\rv32.gpio2_io_out_data[2] ;
+wire	\rv32.gpio2_io_out_data[3] ;
+wire	\rv32.gpio2_io_out_data[4] ;
+wire	\rv32.gpio2_io_out_data[5] ;
+wire	\rv32.gpio2_io_out_data[6] ;
+wire	\rv32.gpio2_io_out_data[7] ;
+wire	\rv32.gpio2_io_out_en[0] ;
+wire	\rv32.gpio2_io_out_en[1] ;
+wire	\rv32.gpio2_io_out_en[2] ;
+wire	\rv32.gpio2_io_out_en[3] ;
+wire	\rv32.gpio2_io_out_en[4] ;
+wire	\rv32.gpio2_io_out_en[5] ;
+wire	\rv32.gpio2_io_out_en[6] ;
+wire	\rv32.gpio2_io_out_en[7] ;
+wire	\rv32.gpio3_io_out_data[0] ;
+wire	\rv32.gpio3_io_out_data[1] ;
+wire	\rv32.gpio3_io_out_data[2] ;
+wire	\rv32.gpio3_io_out_data[3] ;
+wire	\rv32.gpio3_io_out_data[4] ;
+wire	\rv32.gpio3_io_out_data[5] ;
+wire	\rv32.gpio3_io_out_data[6] ;
+wire	\rv32.gpio3_io_out_data[7] ;
+wire	\rv32.gpio3_io_out_en[0] ;
+wire	\rv32.gpio3_io_out_en[1] ;
+wire	\rv32.gpio3_io_out_en[2] ;
+wire	\rv32.gpio3_io_out_en[3] ;
+wire	\rv32.gpio3_io_out_en[4] ;
+wire	\rv32.gpio3_io_out_en[5] ;
+wire	\rv32.gpio3_io_out_en[6] ;
+wire	\rv32.gpio3_io_out_en[7] ;
+wire	\rv32.gpio4_io_out_data[0] ;
+wire	\rv32.gpio4_io_out_data[1] ;
+wire	\rv32.gpio4_io_out_data[2] ;
+wire	\rv32.gpio4_io_out_data[3] ;
+wire	\rv32.gpio4_io_out_data[4] ;
+wire	\rv32.gpio4_io_out_data[5] ;
+wire	\rv32.gpio4_io_out_data[6] ;
+wire	\rv32.gpio4_io_out_data[7] ;
+wire	\rv32.gpio4_io_out_en[0] ;
+wire	\rv32.gpio4_io_out_en[1] ;
+wire	\rv32.gpio4_io_out_en[2] ;
+wire	\rv32.gpio4_io_out_en[3] ;
+wire	\rv32.gpio4_io_out_en[4] ;
+wire	\rv32.gpio4_io_out_en[5] ;
+wire	\rv32.gpio4_io_out_en[6] ;
+wire	\rv32.gpio4_io_out_en[7] ;
+wire	\rv32.gpio5_io_out_data[0] ;
+wire	\rv32.gpio5_io_out_data[1] ;
+wire	\rv32.gpio5_io_out_data[2] ;
+wire	\rv32.gpio5_io_out_data[3] ;
+wire	\rv32.gpio5_io_out_data[4] ;
+wire	\rv32.gpio5_io_out_data[5] ;
+wire	\rv32.gpio5_io_out_data[6] ;
+wire	\rv32.gpio5_io_out_data[7] ;
+wire	\rv32.gpio5_io_out_en[0] ;
+wire	\rv32.gpio5_io_out_en[1] ;
+wire	\rv32.gpio5_io_out_en[2] ;
+wire	\rv32.gpio5_io_out_en[3] ;
+wire	\rv32.gpio5_io_out_en[4] ;
+wire	\rv32.gpio5_io_out_en[5] ;
+wire	\rv32.gpio5_io_out_en[6] ;
+wire	\rv32.gpio5_io_out_en[7] ;
+wire	\rv32.gpio6_io_out_data[0] ;
+wire	\rv32.gpio6_io_out_data[1] ;
+wire	\rv32.gpio6_io_out_data[2] ;
+wire	\rv32.gpio6_io_out_data[3] ;
+wire	\rv32.gpio6_io_out_data[4] ;
+wire	\rv32.gpio6_io_out_data[5] ;
+wire	\rv32.gpio6_io_out_data[6] ;
+wire	\rv32.gpio6_io_out_data[7] ;
+wire	\rv32.gpio6_io_out_en[0] ;
+wire	\rv32.gpio6_io_out_en[1] ;
+wire	\rv32.gpio6_io_out_en[2] ;
+wire	\rv32.gpio6_io_out_en[3] ;
+wire	\rv32.gpio6_io_out_en[4] ;
+wire	\rv32.gpio6_io_out_en[5] ;
+wire	\rv32.gpio6_io_out_en[6] ;
+wire	\rv32.gpio6_io_out_en[7] ;
+wire	\rv32.gpio7_io_out_data[0] ;
+wire	\rv32.gpio7_io_out_data[1] ;
+wire	\rv32.gpio7_io_out_data[2] ;
+wire	\rv32.gpio7_io_out_data[3] ;
+wire	\rv32.gpio7_io_out_data[4] ;
+wire	\rv32.gpio7_io_out_data[5] ;
+wire	\rv32.gpio7_io_out_data[6] ;
+wire	\rv32.gpio7_io_out_data[7] ;
+wire	\rv32.gpio7_io_out_en[0] ;
+wire	\rv32.gpio7_io_out_en[1] ;
+wire	\rv32.gpio7_io_out_en[2] ;
+wire	\rv32.gpio7_io_out_en[3] ;
+wire	\rv32.gpio7_io_out_en[4] ;
+wire	\rv32.gpio7_io_out_en[5] ;
+wire	\rv32.gpio7_io_out_en[6] ;
+wire	\rv32.gpio7_io_out_en[7] ;
+wire	\rv32.gpio8_io_out_data[0] ;
+wire	\rv32.gpio8_io_out_data[1] ;
+wire	\rv32.gpio8_io_out_data[2] ;
+wire	\rv32.gpio8_io_out_data[3] ;
+wire	\rv32.gpio8_io_out_data[4] ;
+wire	\rv32.gpio8_io_out_data[5] ;
+wire	\rv32.gpio8_io_out_data[6] ;
+wire	\rv32.gpio8_io_out_data[7] ;
+wire	\rv32.gpio8_io_out_en[0] ;
+wire	\rv32.gpio8_io_out_en[1] ;
+wire	\rv32.gpio8_io_out_en[2] ;
+wire	\rv32.gpio8_io_out_en[3] ;
+wire	\rv32.gpio8_io_out_en[4] ;
+wire	\rv32.gpio8_io_out_en[5] ;
+wire	\rv32.gpio8_io_out_en[6] ;
+wire	\rv32.gpio8_io_out_en[7] ;
+wire	\rv32.gpio9_io_out_data[0] ;
+wire	\rv32.gpio9_io_out_data[1] ;
+wire	\rv32.gpio9_io_out_data[2] ;
+wire	\rv32.gpio9_io_out_data[3] ;
+wire	\rv32.gpio9_io_out_data[4] ;
+wire	\rv32.gpio9_io_out_data[5] ;
+wire	\rv32.gpio9_io_out_data[6] ;
+wire	\rv32.gpio9_io_out_data[7] ;
+wire	\rv32.gpio9_io_out_en[0] ;
+wire	\rv32.gpio9_io_out_en[1] ;
+wire	\rv32.gpio9_io_out_en[2] ;
+wire	\rv32.gpio9_io_out_en[3] ;
+wire	\rv32.gpio9_io_out_en[4] ;
+wire	\rv32.gpio9_io_out_en[5] ;
+wire	\rv32.gpio9_io_out_en[6] ;
+wire	\rv32.gpio9_io_out_en[7] ;
+wire	\rv32.mem_ahb_haddr[0] ;
+wire	\rv32.mem_ahb_haddr[10] ;
+wire	\rv32.mem_ahb_haddr[11] ;
+wire	\rv32.mem_ahb_haddr[12] ;
+wire	\rv32.mem_ahb_haddr[13] ;
+wire	\rv32.mem_ahb_haddr[14] ;
+wire	\rv32.mem_ahb_haddr[15] ;
+wire	\rv32.mem_ahb_haddr[16] ;
+wire	\rv32.mem_ahb_haddr[17] ;
+wire	\rv32.mem_ahb_haddr[18] ;
+wire	\rv32.mem_ahb_haddr[19] ;
+wire	\rv32.mem_ahb_haddr[1] ;
+wire	\rv32.mem_ahb_haddr[20] ;
+wire	\rv32.mem_ahb_haddr[21] ;
+wire	\rv32.mem_ahb_haddr[22] ;
+wire	\rv32.mem_ahb_haddr[23] ;
+wire	\rv32.mem_ahb_haddr[24] ;
+wire	\rv32.mem_ahb_haddr[25] ;
+wire	\rv32.mem_ahb_haddr[26] ;
+wire	\rv32.mem_ahb_haddr[27] ;
+wire	\rv32.mem_ahb_haddr[28] ;
+wire	\rv32.mem_ahb_haddr[29] ;
+wire	\rv32.mem_ahb_haddr[2] ;
+wire	\rv32.mem_ahb_haddr[30] ;
+wire	\rv32.mem_ahb_haddr[31] ;
+wire	\rv32.mem_ahb_haddr[3] ;
+wire	\rv32.mem_ahb_haddr[4] ;
+wire	\rv32.mem_ahb_haddr[5] ;
+wire	\rv32.mem_ahb_haddr[6] ;
+wire	\rv32.mem_ahb_haddr[7] ;
+wire	\rv32.mem_ahb_haddr[8] ;
+wire	\rv32.mem_ahb_haddr[9] ;
+wire	\rv32.mem_ahb_hburst[0] ;
+wire	\rv32.mem_ahb_hburst[1] ;
+wire	\rv32.mem_ahb_hburst[2] ;
+wire	\rv32.mem_ahb_hready ;
+wire	\rv32.mem_ahb_hsize[0] ;
+wire	\rv32.mem_ahb_hsize[1] ;
+wire	\rv32.mem_ahb_hsize[2] ;
+wire	\rv32.mem_ahb_htrans[0] ;
+wire	\rv32.mem_ahb_htrans[1] ;
+wire	\rv32.mem_ahb_hwdata[0] ;
+wire	\rv32.mem_ahb_hwdata[10] ;
+wire	\rv32.mem_ahb_hwdata[11] ;
+wire	\rv32.mem_ahb_hwdata[12] ;
+wire	\rv32.mem_ahb_hwdata[13] ;
+wire	\rv32.mem_ahb_hwdata[14] ;
+wire	\rv32.mem_ahb_hwdata[15] ;
+wire	\rv32.mem_ahb_hwdata[16] ;
+wire	\rv32.mem_ahb_hwdata[17] ;
+wire	\rv32.mem_ahb_hwdata[18] ;
+wire	\rv32.mem_ahb_hwdata[19] ;
+wire	\rv32.mem_ahb_hwdata[1] ;
+wire	\rv32.mem_ahb_hwdata[20] ;
+wire	\rv32.mem_ahb_hwdata[21] ;
+wire	\rv32.mem_ahb_hwdata[22] ;
+wire	\rv32.mem_ahb_hwdata[23] ;
+wire	\rv32.mem_ahb_hwdata[24] ;
+wire	\rv32.mem_ahb_hwdata[25] ;
+wire	\rv32.mem_ahb_hwdata[26] ;
+wire	\rv32.mem_ahb_hwdata[27] ;
+wire	\rv32.mem_ahb_hwdata[28] ;
+wire	\rv32.mem_ahb_hwdata[29] ;
+wire	\rv32.mem_ahb_hwdata[2] ;
+wire	\rv32.mem_ahb_hwdata[30] ;
+wire	\rv32.mem_ahb_hwdata[31] ;
+wire	\rv32.mem_ahb_hwdata[3] ;
+wire	\rv32.mem_ahb_hwdata[4] ;
+wire	\rv32.mem_ahb_hwdata[5] ;
+wire	\rv32.mem_ahb_hwdata[6] ;
+wire	\rv32.mem_ahb_hwdata[7] ;
+wire	\rv32.mem_ahb_hwdata[8] ;
+wire	\rv32.mem_ahb_hwdata[9] ;
+wire	\rv32.mem_ahb_hwrite ;
+wire	\rv32.resetn_out ;
+wire	\rv32.slave_ahb_hrdata[0] ;
+wire	\rv32.slave_ahb_hrdata[10] ;
+wire	\rv32.slave_ahb_hrdata[11] ;
+wire	\rv32.slave_ahb_hrdata[12] ;
+wire	\rv32.slave_ahb_hrdata[13] ;
+wire	\rv32.slave_ahb_hrdata[14] ;
+wire	\rv32.slave_ahb_hrdata[15] ;
+wire	\rv32.slave_ahb_hrdata[16] ;
+wire	\rv32.slave_ahb_hrdata[17] ;
+wire	\rv32.slave_ahb_hrdata[18] ;
+wire	\rv32.slave_ahb_hrdata[19] ;
+wire	\rv32.slave_ahb_hrdata[1] ;
+wire	\rv32.slave_ahb_hrdata[20] ;
+wire	\rv32.slave_ahb_hrdata[21] ;
+wire	\rv32.slave_ahb_hrdata[22] ;
+wire	\rv32.slave_ahb_hrdata[23] ;
+wire	\rv32.slave_ahb_hrdata[24] ;
+wire	\rv32.slave_ahb_hrdata[25] ;
+wire	\rv32.slave_ahb_hrdata[26] ;
+wire	\rv32.slave_ahb_hrdata[27] ;
+wire	\rv32.slave_ahb_hrdata[28] ;
+wire	\rv32.slave_ahb_hrdata[29] ;
+wire	\rv32.slave_ahb_hrdata[2] ;
+wire	\rv32.slave_ahb_hrdata[30] ;
+wire	\rv32.slave_ahb_hrdata[31] ;
+wire	\rv32.slave_ahb_hrdata[3] ;
+wire	\rv32.slave_ahb_hrdata[4] ;
+wire	\rv32.slave_ahb_hrdata[5] ;
+wire	\rv32.slave_ahb_hrdata[6] ;
+wire	\rv32.slave_ahb_hrdata[7] ;
+wire	\rv32.slave_ahb_hrdata[8] ;
+wire	\rv32.slave_ahb_hrdata[9] ;
+wire	\rv32.slave_ahb_hreadyout ;
+wire	\rv32.slave_ahb_hresp ;
+wire	\rv32.swj_JTAGIR[0] ;
+wire	\rv32.swj_JTAGIR[1] ;
+wire	\rv32.swj_JTAGIR[2] ;
+wire	\rv32.swj_JTAGIR[3] ;
+wire	\rv32.swj_JTAGNSW ;
+wire	\rv32.swj_JTAGSTATE[0] ;
+wire	\rv32.swj_JTAGSTATE[1] ;
+wire	\rv32.swj_JTAGSTATE[2] ;
+wire	\rv32.swj_JTAGSTATE[3] ;
+wire	\rv32.sys_ctrl_clkSource[0] ;
+wire	\rv32.sys_ctrl_clkSource[1] ;
+wire	\rv32.sys_ctrl_hseBypass ;
+wire	\rv32.sys_ctrl_hseEnable ;
+wire	\rv32.sys_ctrl_pllEnable ;
+wire	\rv32.sys_ctrl_sleep ;
+wire	\rv32.sys_ctrl_standby ;
+wire	\rv32.sys_ctrl_stop ;
+wire	[31:0] slave_ahb_haddr;
+//wire	slave_ahb_haddr[0];
+//wire	slave_ahb_haddr[10];
+//wire	slave_ahb_haddr[11];
+//wire	slave_ahb_haddr[12];
+//wire	slave_ahb_haddr[13];
+//wire	slave_ahb_haddr[14];
+//wire	slave_ahb_haddr[15];
+//wire	slave_ahb_haddr[16];
+//wire	slave_ahb_haddr[17];
+//wire	slave_ahb_haddr[18];
+//wire	slave_ahb_haddr[19];
+//wire	slave_ahb_haddr[1];
+//wire	slave_ahb_haddr[20];
+//wire	slave_ahb_haddr[21];
+//wire	slave_ahb_haddr[22];
+//wire	slave_ahb_haddr[23];
+//wire	slave_ahb_haddr[24];
+//wire	slave_ahb_haddr[25];
+//wire	slave_ahb_haddr[26];
+//wire	slave_ahb_haddr[27];
+//wire	slave_ahb_haddr[28];
+//wire	slave_ahb_haddr[29];
+//wire	slave_ahb_haddr[2];
+//wire	slave_ahb_haddr[30];
+//wire	slave_ahb_haddr[31];
+//wire	slave_ahb_haddr[3];
+//wire	slave_ahb_haddr[4];
+//wire	slave_ahb_haddr[5];
+//wire	slave_ahb_haddr[6];
+//wire	slave_ahb_haddr[7];
+//wire	slave_ahb_haddr[8];
+//wire	slave_ahb_haddr[9];
+wire	[2:0] slave_ahb_hburst;
+//wire	slave_ahb_hburst[0];
+//wire	slave_ahb_hburst[1];
+//wire	slave_ahb_hburst[2];
+wire	\slave_ahb_hready~combout ;
+wire	\slave_ahb_hsel~combout ;
+wire	[2:0] slave_ahb_hsize;
+//wire	slave_ahb_hsize[0];
+//wire	slave_ahb_hsize[1];
+//wire	slave_ahb_hsize[2];
+wire	[1:0] slave_ahb_htrans;
+//wire	slave_ahb_htrans[0];
+//wire	slave_ahb_htrans[1];
+wire	[31:0] slave_ahb_hwdata;
+//wire	slave_ahb_hwdata[0];
+//wire	slave_ahb_hwdata[10];
+//wire	slave_ahb_hwdata[11];
+//wire	slave_ahb_hwdata[12];
+//wire	slave_ahb_hwdata[13];
+//wire	slave_ahb_hwdata[14];
+//wire	slave_ahb_hwdata[15];
+//wire	slave_ahb_hwdata[16];
+//wire	slave_ahb_hwdata[17];
+//wire	slave_ahb_hwdata[18];
+//wire	slave_ahb_hwdata[19];
+//wire	slave_ahb_hwdata[1];
+//wire	slave_ahb_hwdata[20];
+//wire	slave_ahb_hwdata[21];
+//wire	slave_ahb_hwdata[22];
+//wire	slave_ahb_hwdata[23];
+//wire	slave_ahb_hwdata[24];
+//wire	slave_ahb_hwdata[25];
+//wire	slave_ahb_hwdata[26];
+//wire	slave_ahb_hwdata[27];
+//wire	slave_ahb_hwdata[28];
+//wire	slave_ahb_hwdata[29];
+//wire	slave_ahb_hwdata[2];
+//wire	slave_ahb_hwdata[30];
+//wire	slave_ahb_hwdata[31];
+//wire	slave_ahb_hwdata[3];
+//wire	slave_ahb_hwdata[4];
+//wire	slave_ahb_hwdata[5];
+//wire	slave_ahb_hwdata[6];
+//wire	slave_ahb_hwdata[7];
+//wire	slave_ahb_hwdata[8];
+//wire	slave_ahb_hwdata[9];
+wire	\slave_ahb_hwrite~combout ;
+wire	unknown;
+wire	\~GND~combout ;
+wire	\~VCC~combout ;
+
+wire vcc;
+wire gnd;
+assign vcc = 1'b1;
+assign gnd = 1'b0;
+
+alta_rio \PIN_1~output (
+	.padio(PIN_1),
+	.datain(\rv32.gpio1_io_out_data[3] ),
+	.oe(\rv32.gpio1_io_out_en[3] ),
+	.outclk(gnd),
+	.outclkena(vcc),
+	.inclk(gnd),
+	.inclkena(vcc),
+	.areset(gnd),
+	.sreset(gnd),
+	.combout(\PIN_1~input_o ),
+	.regout());
+defparam \PIN_1~output .coord_x = 22;
+defparam \PIN_1~output .coord_y = 1;
+defparam \PIN_1~output .coord_z = 4;
+defparam \PIN_1~output .IN_ASYNC_MODE = 1'b0;
+defparam \PIN_1~output .IN_SYNC_MODE = 1'b0;
+defparam \PIN_1~output .IN_POWERUP = 1'b0;
+defparam \PIN_1~output .OUT_REG_MODE = 1'b0;
+defparam \PIN_1~output .OUT_ASYNC_MODE = 1'b0;
+defparam \PIN_1~output .OUT_SYNC_MODE = 1'b0;
+defparam \PIN_1~output .OUT_POWERUP = 1'b0;
+defparam \PIN_1~output .OE_REG_MODE = 1'b0;
+defparam \PIN_1~output .OE_ASYNC_MODE = 1'b0;
+defparam \PIN_1~output .OE_SYNC_MODE = 1'b0;
+defparam \PIN_1~output .OE_POWERUP = 1'b0;
+defparam \PIN_1~output .CFG_TRI_INPUT = 1'b0;
+defparam \PIN_1~output .CFG_INPUT_EN = 1'b1;
+defparam \PIN_1~output .CFG_PULL_UP = 1'b0;
+defparam \PIN_1~output .CFG_SLR = 1'b0;
+defparam \PIN_1~output .CFG_OPEN_DRAIN = 1'b0;
+defparam \PIN_1~output .CFG_PDRCTRL = 4'b0100;
+defparam \PIN_1~output .CFG_KEEP = 2'b00;
+defparam \PIN_1~output .CFG_LVDS_OUT_EN = 1'b0;
+defparam \PIN_1~output .CFG_LVDS_SEL_CUA = 2'b00;
+defparam \PIN_1~output .CFG_LVDS_IREF = 10'b0110000000;
+defparam \PIN_1~output .CFG_LVDS_IN_EN = 1'b0;
+defparam \PIN_1~output .DPCLK_DELAY = 4'b0000;
+defparam \PIN_1~output .OUT_DELAY = 1'b0;
+defparam \PIN_1~output .IN_DATA_DELAY = 3'b000;
+defparam \PIN_1~output .IN_REG_DELAY = 3'b000;
+
+alta_rio \PIN_2~output (
+	.padio(PIN_2),
+	.datain(\rv32.gpio1_io_out_data[0] ),
+	.oe(\rv32.gpio1_io_out_en[0] ),
+	.outclk(gnd),
+	.outclkena(vcc),
+	.inclk(gnd),
+	.inclkena(vcc),
+	.areset(gnd),
+	.sreset(gnd),
+	.combout(\PIN_2~input_o ),
+	.regout());
+defparam \PIN_2~output .coord_x = 22;
+defparam \PIN_2~output .coord_y = 1;
+defparam \PIN_2~output .coord_z = 3;
+defparam \PIN_2~output .IN_ASYNC_MODE = 1'b0;
+defparam \PIN_2~output .IN_SYNC_MODE = 1'b0;
+defparam \PIN_2~output .IN_POWERUP = 1'b0;
+defparam \PIN_2~output .OUT_REG_MODE = 1'b0;
+defparam \PIN_2~output .OUT_ASYNC_MODE = 1'b0;
+defparam \PIN_2~output .OUT_SYNC_MODE = 1'b0;
+defparam \PIN_2~output .OUT_POWERUP = 1'b0;
+defparam \PIN_2~output .OE_REG_MODE = 1'b0;
+defparam \PIN_2~output .OE_ASYNC_MODE = 1'b0;
+defparam \PIN_2~output .OE_SYNC_MODE = 1'b0;
+defparam \PIN_2~output .OE_POWERUP = 1'b0;
+defparam \PIN_2~output .CFG_TRI_INPUT = 1'b0;
+defparam \PIN_2~output .CFG_INPUT_EN = 1'b1;
+defparam \PIN_2~output .CFG_PULL_UP = 1'b0;
+defparam \PIN_2~output .CFG_SLR = 1'b0;
+defparam \PIN_2~output .CFG_OPEN_DRAIN = 1'b0;
+defparam \PIN_2~output .CFG_PDRCTRL = 4'b0100;
+defparam \PIN_2~output .CFG_KEEP = 2'b00;
+defparam \PIN_2~output .CFG_LVDS_OUT_EN = 1'b0;
+defparam \PIN_2~output .CFG_LVDS_SEL_CUA = 2'b00;
+defparam \PIN_2~output .CFG_LVDS_IREF = 10'b0110000000;
+defparam \PIN_2~output .CFG_LVDS_IN_EN = 1'b0;
+defparam \PIN_2~output .DPCLK_DELAY = 4'b0000;
+defparam \PIN_2~output .OUT_DELAY = 1'b0;
+defparam \PIN_2~output .IN_DATA_DELAY = 3'b000;
+defparam \PIN_2~output .IN_REG_DELAY = 3'b000;
+
+alta_rio \PIN_3~output (
+	.padio(PIN_3),
+	.datain(\rv32.gpio1_io_out_data[1] ),
+	.oe(\rv32.gpio1_io_out_en[1] ),
+	.outclk(gnd),
+	.outclkena(vcc),
+	.inclk(gnd),
+	.inclkena(vcc),
+	.areset(gnd),
+	.sreset(gnd),
+	.combout(\PIN_3~input_o ),
+	.regout());
+defparam \PIN_3~output .coord_x = 22;
+defparam \PIN_3~output .coord_y = 1;
+defparam \PIN_3~output .coord_z = 2;
+defparam \PIN_3~output .IN_ASYNC_MODE = 1'b0;
+defparam \PIN_3~output .IN_SYNC_MODE = 1'b0;
+defparam \PIN_3~output .IN_POWERUP = 1'b0;
+defparam \PIN_3~output .OUT_REG_MODE = 1'b0;
+defparam \PIN_3~output .OUT_ASYNC_MODE = 1'b0;
+defparam \PIN_3~output .OUT_SYNC_MODE = 1'b0;
+defparam \PIN_3~output .OUT_POWERUP = 1'b0;
+defparam \PIN_3~output .OE_REG_MODE = 1'b0;
+defparam \PIN_3~output .OE_ASYNC_MODE = 1'b0;
+defparam \PIN_3~output .OE_SYNC_MODE = 1'b0;
+defparam \PIN_3~output .OE_POWERUP = 1'b0;
+defparam \PIN_3~output .CFG_TRI_INPUT = 1'b0;
+defparam \PIN_3~output .CFG_INPUT_EN = 1'b1;
+defparam \PIN_3~output .CFG_PULL_UP = 1'b0;
+defparam \PIN_3~output .CFG_SLR = 1'b0;
+defparam \PIN_3~output .CFG_OPEN_DRAIN = 1'b0;
+defparam \PIN_3~output .CFG_PDRCTRL = 4'b0100;
+defparam \PIN_3~output .CFG_KEEP = 2'b00;
+defparam \PIN_3~output .CFG_LVDS_OUT_EN = 1'b0;
+defparam \PIN_3~output .CFG_LVDS_SEL_CUA = 2'b00;
+defparam \PIN_3~output .CFG_LVDS_IREF = 10'b0110000000;
+defparam \PIN_3~output .CFG_LVDS_IN_EN = 1'b0;
+defparam \PIN_3~output .DPCLK_DELAY = 4'b0000;
+defparam \PIN_3~output .OUT_DELAY = 1'b0;
+defparam \PIN_3~output .IN_DATA_DELAY = 3'b000;
+defparam \PIN_3~output .IN_REG_DELAY = 3'b000;
+
+alta_rio \PIN_68~output (
+	.padio(PIN_68),
+	.datain(\rv32.gpio7_io_out_data[6] ),
+	.oe(\rv32.gpio7_io_out_en[6] ),
+	.outclk(gnd),
+	.outclkena(vcc),
+	.inclk(gnd),
+	.inclkena(vcc),
+	.areset(gnd),
+	.sreset(gnd),
+	.combout(),
+	.regout());
+defparam \PIN_68~output .coord_x = 0;
+defparam \PIN_68~output .coord_y = 2;
+defparam \PIN_68~output .coord_z = 5;
+defparam \PIN_68~output .IN_ASYNC_MODE = 1'b0;
+defparam \PIN_68~output .IN_SYNC_MODE = 1'b0;
+defparam \PIN_68~output .IN_POWERUP = 1'b0;
+defparam \PIN_68~output .OUT_REG_MODE = 1'b0;
+defparam \PIN_68~output .OUT_ASYNC_MODE = 1'b0;
+defparam \PIN_68~output .OUT_SYNC_MODE = 1'b0;
+defparam \PIN_68~output .OUT_POWERUP = 1'b0;
+defparam \PIN_68~output .OE_REG_MODE = 1'b0;
+defparam \PIN_68~output .OE_ASYNC_MODE = 1'b0;
+defparam \PIN_68~output .OE_SYNC_MODE = 1'b0;
+defparam \PIN_68~output .OE_POWERUP = 1'b0;
+defparam \PIN_68~output .CFG_TRI_INPUT = 1'b0;
+defparam \PIN_68~output .CFG_INPUT_EN = 1'b0;
+defparam \PIN_68~output .CFG_PULL_UP = 1'b0;
+defparam \PIN_68~output .CFG_SLR = 1'b0;
+defparam \PIN_68~output .CFG_OPEN_DRAIN = 1'b0;
+defparam \PIN_68~output .CFG_PDRCTRL = 4'b0100;
+defparam \PIN_68~output .CFG_KEEP = 2'b00;
+defparam \PIN_68~output .CFG_LVDS_OUT_EN = 1'b0;
+defparam \PIN_68~output .CFG_LVDS_SEL_CUA = 2'b00;
+defparam \PIN_68~output .CFG_LVDS_IREF = 10'b0110000000;
+defparam \PIN_68~output .CFG_LVDS_IN_EN = 1'b0;
+defparam \PIN_68~output .DPCLK_DELAY = 4'b0000;
+defparam \PIN_68~output .OUT_DELAY = 1'b0;
+defparam \PIN_68~output .IN_DATA_DELAY = 3'b000;
+defparam \PIN_68~output .IN_REG_DELAY = 3'b000;
+
+alta_rio \PIN_69~input (
+	.padio(PIN_69),
+	.datain(gnd),
+	.oe(gnd),
+	.outclk(gnd),
+	.outclkena(vcc),
+	.inclk(gnd),
+	.inclkena(vcc),
+	.areset(gnd),
+	.sreset(gnd),
+	.combout(\PIN_69~input_o ),
+	.regout());
+defparam \PIN_69~input .coord_x = 0;
+defparam \PIN_69~input .coord_y = 1;
+defparam \PIN_69~input .coord_z = 0;
+defparam \PIN_69~input .IN_ASYNC_MODE = 1'b0;
+defparam \PIN_69~input .IN_SYNC_MODE = 1'b0;
+defparam \PIN_69~input .IN_POWERUP = 1'b0;
+defparam \PIN_69~input .OUT_REG_MODE = 1'b0;
+defparam \PIN_69~input .OUT_ASYNC_MODE = 1'b0;
+defparam \PIN_69~input .OUT_SYNC_MODE = 1'b0;
+defparam \PIN_69~input .OUT_POWERUP = 1'b0;
+defparam \PIN_69~input .OE_REG_MODE = 1'b0;
+defparam \PIN_69~input .OE_ASYNC_MODE = 1'b0;
+defparam \PIN_69~input .OE_SYNC_MODE = 1'b0;
+defparam \PIN_69~input .OE_POWERUP = 1'b0;
+defparam \PIN_69~input .CFG_TRI_INPUT = 1'b0;
+defparam \PIN_69~input .CFG_INPUT_EN = 1'b1;
+defparam \PIN_69~input .CFG_PULL_UP = 1'b0;
+defparam \PIN_69~input .CFG_SLR = 1'b0;
+defparam \PIN_69~input .CFG_OPEN_DRAIN = 1'b0;
+defparam \PIN_69~input .CFG_PDRCTRL = 4'b0100;
+defparam \PIN_69~input .CFG_KEEP = 2'b00;
+defparam \PIN_69~input .CFG_LVDS_OUT_EN = 1'b0;
+defparam \PIN_69~input .CFG_LVDS_SEL_CUA = 2'b00;
+defparam \PIN_69~input .CFG_LVDS_IREF = 10'b0110000000;
+defparam \PIN_69~input .CFG_LVDS_IN_EN = 1'b0;
+defparam \PIN_69~input .DPCLK_DELAY = 4'b0000;
+defparam \PIN_69~input .OUT_DELAY = 1'b0;
+defparam \PIN_69~input .IN_DATA_DELAY = 3'b000;
+defparam \PIN_69~input .IN_REG_DELAY = 3'b000;
+
+alta_rio \PIN_88~output (
+	.padio(PIN_88),
+	.datain(\rv32.gpio1_io_out_data[6] ),
+	.oe(\rv32.gpio1_io_out_en[6] ),
+	.outclk(gnd),
+	.outclkena(vcc),
+	.inclk(gnd),
+	.inclkena(vcc),
+	.areset(gnd),
+	.sreset(gnd),
+	.combout(\PIN_88~input_o ),
+	.regout());
+defparam \PIN_88~output .coord_x = 8;
+defparam \PIN_88~output .coord_y = 0;
+defparam \PIN_88~output .coord_z = 3;
+defparam \PIN_88~output .IN_ASYNC_MODE = 1'b0;
+defparam \PIN_88~output .IN_SYNC_MODE = 1'b0;
+defparam \PIN_88~output .IN_POWERUP = 1'b0;
+defparam \PIN_88~output .OUT_REG_MODE = 1'b0;
+defparam \PIN_88~output .OUT_ASYNC_MODE = 1'b0;
+defparam \PIN_88~output .OUT_SYNC_MODE = 1'b0;
+defparam \PIN_88~output .OUT_POWERUP = 1'b0;
+defparam \PIN_88~output .OE_REG_MODE = 1'b0;
+defparam \PIN_88~output .OE_ASYNC_MODE = 1'b0;
+defparam \PIN_88~output .OE_SYNC_MODE = 1'b0;
+defparam \PIN_88~output .OE_POWERUP = 1'b0;
+defparam \PIN_88~output .CFG_TRI_INPUT = 1'b0;
+defparam \PIN_88~output .CFG_INPUT_EN = 1'b1;
+defparam \PIN_88~output .CFG_PULL_UP = 1'b0;
+defparam \PIN_88~output .CFG_SLR = 1'b0;
+defparam \PIN_88~output .CFG_OPEN_DRAIN = 1'b0;
+defparam \PIN_88~output .CFG_PDRCTRL = 4'b0100;
+defparam \PIN_88~output .CFG_KEEP = 2'b00;
+defparam \PIN_88~output .CFG_LVDS_OUT_EN = 1'b0;
+defparam \PIN_88~output .CFG_LVDS_SEL_CUA = 2'b00;
+defparam \PIN_88~output .CFG_LVDS_IREF = 10'b0110000000;
+defparam \PIN_88~output .CFG_LVDS_IN_EN = 1'b0;
+defparam \PIN_88~output .DPCLK_DELAY = 4'b0000;
+defparam \PIN_88~output .OUT_DELAY = 1'b0;
+defparam \PIN_88~output .IN_DATA_DELAY = 3'b000;
+defparam \PIN_88~output .IN_REG_DELAY = 3'b000;
+
+alta_rio \PIN_91~output (
+	.padio(PIN_91),
+	.datain(\rv32.gpio1_io_out_data[5] ),
+	.oe(\rv32.gpio1_io_out_en[5] ),
+	.outclk(gnd),
+	.outclkena(vcc),
+	.inclk(gnd),
+	.inclkena(vcc),
+	.areset(gnd),
+	.sreset(gnd),
+	.combout(\PIN_91~input_o ),
+	.regout());
+defparam \PIN_91~output .coord_x = 17;
+defparam \PIN_91~output .coord_y = 0;
+defparam \PIN_91~output .coord_z = 2;
+defparam \PIN_91~output .IN_ASYNC_MODE = 1'b0;
+defparam \PIN_91~output .IN_SYNC_MODE = 1'b0;
+defparam \PIN_91~output .IN_POWERUP = 1'b0;
+defparam \PIN_91~output .OUT_REG_MODE = 1'b0;
+defparam \PIN_91~output .OUT_ASYNC_MODE = 1'b0;
+defparam \PIN_91~output .OUT_SYNC_MODE = 1'b0;
+defparam \PIN_91~output .OUT_POWERUP = 1'b0;
+defparam \PIN_91~output .OE_REG_MODE = 1'b0;
+defparam \PIN_91~output .OE_ASYNC_MODE = 1'b0;
+defparam \PIN_91~output .OE_SYNC_MODE = 1'b0;
+defparam \PIN_91~output .OE_POWERUP = 1'b0;
+defparam \PIN_91~output .CFG_TRI_INPUT = 1'b0;
+defparam \PIN_91~output .CFG_INPUT_EN = 1'b1;
+defparam \PIN_91~output .CFG_PULL_UP = 1'b0;
+defparam \PIN_91~output .CFG_SLR = 1'b0;
+defparam \PIN_91~output .CFG_OPEN_DRAIN = 1'b0;
+defparam \PIN_91~output .CFG_PDRCTRL = 4'b0100;
+defparam \PIN_91~output .CFG_KEEP = 2'b00;
+defparam \PIN_91~output .CFG_LVDS_OUT_EN = 1'b0;
+defparam \PIN_91~output .CFG_LVDS_SEL_CUA = 2'b00;
+defparam \PIN_91~output .CFG_LVDS_IREF = 10'b0110000000;
+defparam \PIN_91~output .CFG_LVDS_IN_EN = 1'b0;
+defparam \PIN_91~output .DPCLK_DELAY = 4'b0000;
+defparam \PIN_91~output .OUT_DELAY = 1'b0;
+defparam \PIN_91~output .IN_DATA_DELAY = 3'b000;
+defparam \PIN_91~output .IN_REG_DELAY = 3'b000;
+
+alta_rio \PIN_92~output (
+	.padio(PIN_92),
+	.datain(\rv32.gpio1_io_out_data[4] ),
+	.oe(\rv32.gpio1_io_out_en[4] ),
+	.outclk(gnd),
+	.outclkena(vcc),
+	.inclk(gnd),
+	.inclkena(vcc),
+	.areset(gnd),
+	.sreset(gnd),
+	.combout(\PIN_92~input_o ),
+	.regout());
+defparam \PIN_92~output .coord_x = 18;
+defparam \PIN_92~output .coord_y = 0;
+defparam \PIN_92~output .coord_z = 0;
+defparam \PIN_92~output .IN_ASYNC_MODE = 1'b0;
+defparam \PIN_92~output .IN_SYNC_MODE = 1'b0;
+defparam \PIN_92~output .IN_POWERUP = 1'b0;
+defparam \PIN_92~output .OUT_REG_MODE = 1'b0;
+defparam \PIN_92~output .OUT_ASYNC_MODE = 1'b0;
+defparam \PIN_92~output .OUT_SYNC_MODE = 1'b0;
+defparam \PIN_92~output .OUT_POWERUP = 1'b0;
+defparam \PIN_92~output .OE_REG_MODE = 1'b0;
+defparam \PIN_92~output .OE_ASYNC_MODE = 1'b0;
+defparam \PIN_92~output .OE_SYNC_MODE = 1'b0;
+defparam \PIN_92~output .OE_POWERUP = 1'b0;
+defparam \PIN_92~output .CFG_TRI_INPUT = 1'b0;
+defparam \PIN_92~output .CFG_INPUT_EN = 1'b1;
+defparam \PIN_92~output .CFG_PULL_UP = 1'b0;
+defparam \PIN_92~output .CFG_SLR = 1'b0;
+defparam \PIN_92~output .CFG_OPEN_DRAIN = 1'b0;
+defparam \PIN_92~output .CFG_PDRCTRL = 4'b0100;
+defparam \PIN_92~output .CFG_KEEP = 2'b00;
+defparam \PIN_92~output .CFG_LVDS_OUT_EN = 1'b0;
+defparam \PIN_92~output .CFG_LVDS_SEL_CUA = 2'b00;
+defparam \PIN_92~output .CFG_LVDS_IREF = 10'b0110000000;
+defparam \PIN_92~output .CFG_LVDS_IN_EN = 1'b0;
+defparam \PIN_92~output .DPCLK_DELAY = 4'b0000;
+defparam \PIN_92~output .OUT_DELAY = 1'b0;
+defparam \PIN_92~output .IN_DATA_DELAY = 3'b000;
+defparam \PIN_92~output .IN_REG_DELAY = 3'b000;
+
+alta_rio \PIN_95~output (
+	.padio(PIN_95),
+	.datain(\rv32.gpio2_io_out_data[1] ),
+	.oe(\rv32.gpio2_io_out_en[1] ),
+	.outclk(gnd),
+	.outclkena(vcc),
+	.inclk(gnd),
+	.inclkena(vcc),
+	.areset(gnd),
+	.sreset(gnd),
+	.combout(\PIN_95~input_o ),
+	.regout());
+defparam \PIN_95~output .coord_x = 19;
+defparam \PIN_95~output .coord_y = 0;
+defparam \PIN_95~output .coord_z = 1;
+defparam \PIN_95~output .IN_ASYNC_MODE = 1'b0;
+defparam \PIN_95~output .IN_SYNC_MODE = 1'b0;
+defparam \PIN_95~output .IN_POWERUP = 1'b0;
+defparam \PIN_95~output .OUT_REG_MODE = 1'b0;
+defparam \PIN_95~output .OUT_ASYNC_MODE = 1'b0;
+defparam \PIN_95~output .OUT_SYNC_MODE = 1'b0;
+defparam \PIN_95~output .OUT_POWERUP = 1'b0;
+defparam \PIN_95~output .OE_REG_MODE = 1'b0;
+defparam \PIN_95~output .OE_ASYNC_MODE = 1'b0;
+defparam \PIN_95~output .OE_SYNC_MODE = 1'b0;
+defparam \PIN_95~output .OE_POWERUP = 1'b0;
+defparam \PIN_95~output .CFG_TRI_INPUT = 1'b0;
+defparam \PIN_95~output .CFG_INPUT_EN = 1'b1;
+defparam \PIN_95~output .CFG_PULL_UP = 1'b0;
+defparam \PIN_95~output .CFG_SLR = 1'b0;
+defparam \PIN_95~output .CFG_OPEN_DRAIN = 1'b0;
+defparam \PIN_95~output .CFG_PDRCTRL = 4'b0100;
+defparam \PIN_95~output .CFG_KEEP = 2'b00;
+defparam \PIN_95~output .CFG_LVDS_OUT_EN = 1'b0;
+defparam \PIN_95~output .CFG_LVDS_SEL_CUA = 2'b00;
+defparam \PIN_95~output .CFG_LVDS_IREF = 10'b0110000000;
+defparam \PIN_95~output .CFG_LVDS_IN_EN = 1'b0;
+defparam \PIN_95~output .DPCLK_DELAY = 4'b0000;
+defparam \PIN_95~output .OUT_DELAY = 1'b0;
+defparam \PIN_95~output .IN_DATA_DELAY = 3'b000;
+defparam \PIN_95~output .IN_REG_DELAY = 3'b000;
+
+alta_rio \PIN_96~output (
+	.padio(PIN_96),
+	.datain(\rv32.gpio2_io_out_data[2] ),
+	.oe(\rv32.gpio2_io_out_en[2] ),
+	.outclk(gnd),
+	.outclkena(vcc),
+	.inclk(gnd),
+	.inclkena(vcc),
+	.areset(gnd),
+	.sreset(gnd),
+	.combout(\PIN_96~input_o ),
+	.regout());
+defparam \PIN_96~output .coord_x = 19;
+defparam \PIN_96~output .coord_y = 0;
+defparam \PIN_96~output .coord_z = 3;
+defparam \PIN_96~output .IN_ASYNC_MODE = 1'b0;
+defparam \PIN_96~output .IN_SYNC_MODE = 1'b0;
+defparam \PIN_96~output .IN_POWERUP = 1'b0;
+defparam \PIN_96~output .OUT_REG_MODE = 1'b0;
+defparam \PIN_96~output .OUT_ASYNC_MODE = 1'b0;
+defparam \PIN_96~output .OUT_SYNC_MODE = 1'b0;
+defparam \PIN_96~output .OUT_POWERUP = 1'b0;
+defparam \PIN_96~output .OE_REG_MODE = 1'b0;
+defparam \PIN_96~output .OE_ASYNC_MODE = 1'b0;
+defparam \PIN_96~output .OE_SYNC_MODE = 1'b0;
+defparam \PIN_96~output .OE_POWERUP = 1'b0;
+defparam \PIN_96~output .CFG_TRI_INPUT = 1'b0;
+defparam \PIN_96~output .CFG_INPUT_EN = 1'b1;
+defparam \PIN_96~output .CFG_PULL_UP = 1'b0;
+defparam \PIN_96~output .CFG_SLR = 1'b0;
+defparam \PIN_96~output .CFG_OPEN_DRAIN = 1'b0;
+defparam \PIN_96~output .CFG_PDRCTRL = 4'b0100;
+defparam \PIN_96~output .CFG_KEEP = 2'b00;
+defparam \PIN_96~output .CFG_LVDS_OUT_EN = 1'b0;
+defparam \PIN_96~output .CFG_LVDS_SEL_CUA = 2'b00;
+defparam \PIN_96~output .CFG_LVDS_IREF = 10'b0110000000;
+defparam \PIN_96~output .CFG_LVDS_IN_EN = 1'b0;
+defparam \PIN_96~output .DPCLK_DELAY = 4'b0000;
+defparam \PIN_96~output .OUT_DELAY = 1'b0;
+defparam \PIN_96~output .IN_DATA_DELAY = 3'b000;
+defparam \PIN_96~output .IN_REG_DELAY = 3'b000;
+
+alta_rio \PIN_97~output (
+	.padio(PIN_97),
+	.datain(\rv32.gpio2_io_out_data[0] ),
+	.oe(\rv32.gpio2_io_out_en[0] ),
+	.outclk(gnd),
+	.outclkena(vcc),
+	.inclk(gnd),
+	.inclkena(vcc),
+	.areset(gnd),
+	.sreset(gnd),
+	.combout(\PIN_97~input_o ),
+	.regout());
+defparam \PIN_97~output .coord_x = 20;
+defparam \PIN_97~output .coord_y = 0;
+defparam \PIN_97~output .coord_z = 0;
+defparam \PIN_97~output .IN_ASYNC_MODE = 1'b0;
+defparam \PIN_97~output .IN_SYNC_MODE = 1'b0;
+defparam \PIN_97~output .IN_POWERUP = 1'b0;
+defparam \PIN_97~output .OUT_REG_MODE = 1'b0;
+defparam \PIN_97~output .OUT_ASYNC_MODE = 1'b0;
+defparam \PIN_97~output .OUT_SYNC_MODE = 1'b0;
+defparam \PIN_97~output .OUT_POWERUP = 1'b0;
+defparam \PIN_97~output .OE_REG_MODE = 1'b0;
+defparam \PIN_97~output .OE_ASYNC_MODE = 1'b0;
+defparam \PIN_97~output .OE_SYNC_MODE = 1'b0;
+defparam \PIN_97~output .OE_POWERUP = 1'b0;
+defparam \PIN_97~output .CFG_TRI_INPUT = 1'b0;
+defparam \PIN_97~output .CFG_INPUT_EN = 1'b1;
+defparam \PIN_97~output .CFG_PULL_UP = 1'b0;
+defparam \PIN_97~output .CFG_SLR = 1'b0;
+defparam \PIN_97~output .CFG_OPEN_DRAIN = 1'b0;
+defparam \PIN_97~output .CFG_PDRCTRL = 4'b0100;
+defparam \PIN_97~output .CFG_KEEP = 2'b00;
+defparam \PIN_97~output .CFG_LVDS_OUT_EN = 1'b0;
+defparam \PIN_97~output .CFG_LVDS_SEL_CUA = 2'b00;
+defparam \PIN_97~output .CFG_LVDS_IREF = 10'b0110000000;
+defparam \PIN_97~output .CFG_LVDS_IN_EN = 1'b0;
+defparam \PIN_97~output .DPCLK_DELAY = 4'b0000;
+defparam \PIN_97~output .OUT_DELAY = 1'b0;
+defparam \PIN_97~output .IN_DATA_DELAY = 3'b000;
+defparam \PIN_97~output .IN_REG_DELAY = 3'b000;
+
+alta_rio \PIN_HSE~input (
+	.padio(PIN_HSE),
+	.datain(gnd),
+	.oe(gnd),
+	.outclk(gnd),
+	.outclkena(vcc),
+	.inclk(gnd),
+	.inclkena(vcc),
+	.areset(gnd),
+	.sreset(gnd),
+	.combout(\PIN_HSE~input_o ),
+	.regout());
+defparam \PIN_HSE~input .coord_x = 22;
+defparam \PIN_HSE~input .coord_y = 4;
+defparam \PIN_HSE~input .coord_z = 1;
+defparam \PIN_HSE~input .IN_ASYNC_MODE = 1'b0;
+defparam \PIN_HSE~input .IN_SYNC_MODE = 1'b0;
+defparam \PIN_HSE~input .IN_POWERUP = 1'b0;
+defparam \PIN_HSE~input .OUT_REG_MODE = 1'b0;
+defparam \PIN_HSE~input .OUT_ASYNC_MODE = 1'b0;
+defparam \PIN_HSE~input .OUT_SYNC_MODE = 1'b0;
+defparam \PIN_HSE~input .OUT_POWERUP = 1'b0;
+defparam \PIN_HSE~input .OE_REG_MODE = 1'b0;
+defparam \PIN_HSE~input .OE_ASYNC_MODE = 1'b0;
+defparam \PIN_HSE~input .OE_SYNC_MODE = 1'b0;
+defparam \PIN_HSE~input .OE_POWERUP = 1'b0;
+defparam \PIN_HSE~input .CFG_TRI_INPUT = 1'b0;
+defparam \PIN_HSE~input .CFG_PULL_UP = 1'b0;
+defparam \PIN_HSE~input .CFG_SLR = 1'b0;
+defparam \PIN_HSE~input .CFG_OPEN_DRAIN = 1'b0;
+defparam \PIN_HSE~input .CFG_PDRCTRL = 4'b0010;
+defparam \PIN_HSE~input .CFG_KEEP = 2'b00;
+defparam \PIN_HSE~input .CFG_LVDS_OUT_EN = 1'b0;
+defparam \PIN_HSE~input .CFG_LVDS_SEL_CUA = 2'b00;
+defparam \PIN_HSE~input .CFG_LVDS_IREF = 10'b0110000000;
+defparam \PIN_HSE~input .CFG_LVDS_IN_EN = 1'b0;
+defparam \PIN_HSE~input .DPCLK_DELAY = 4'b0000;
+defparam \PIN_HSE~input .OUT_DELAY = 1'b0;
+defparam \PIN_HSE~input .IN_DATA_DELAY = 3'b000;
+defparam \PIN_HSE~input .IN_REG_DELAY = 3'b000;
+
+alta_rio \PIN_HSI~input (
+	.padio(PIN_HSI),
+	.datain(gnd),
+	.oe(gnd),
+	.outclk(gnd),
+	.outclkena(vcc),
+	.inclk(gnd),
+	.inclkena(vcc),
+	.areset(gnd),
+	.sreset(gnd),
+	.combout(\PIN_HSI~input_o ),
+	.regout());
+defparam \PIN_HSI~input .coord_x = 22;
+defparam \PIN_HSI~input .coord_y = 4;
+defparam \PIN_HSI~input .coord_z = 0;
+defparam \PIN_HSI~input .IN_ASYNC_MODE = 1'b0;
+defparam \PIN_HSI~input .IN_SYNC_MODE = 1'b0;
+defparam \PIN_HSI~input .IN_POWERUP = 1'b0;
+defparam \PIN_HSI~input .OUT_REG_MODE = 1'b0;
+defparam \PIN_HSI~input .OUT_ASYNC_MODE = 1'b0;
+defparam \PIN_HSI~input .OUT_SYNC_MODE = 1'b0;
+defparam \PIN_HSI~input .OUT_POWERUP = 1'b0;
+defparam \PIN_HSI~input .OE_REG_MODE = 1'b0;
+defparam \PIN_HSI~input .OE_ASYNC_MODE = 1'b0;
+defparam \PIN_HSI~input .OE_SYNC_MODE = 1'b0;
+defparam \PIN_HSI~input .OE_POWERUP = 1'b0;
+defparam \PIN_HSI~input .CFG_TRI_INPUT = 1'b0;
+defparam \PIN_HSI~input .CFG_PULL_UP = 1'b0;
+defparam \PIN_HSI~input .CFG_SLR = 1'b0;
+defparam \PIN_HSI~input .CFG_OPEN_DRAIN = 1'b0;
+defparam \PIN_HSI~input .CFG_PDRCTRL = 4'b0010;
+defparam \PIN_HSI~input .CFG_KEEP = 2'b00;
+defparam \PIN_HSI~input .CFG_LVDS_OUT_EN = 1'b0;
+defparam \PIN_HSI~input .CFG_LVDS_SEL_CUA = 2'b00;
+defparam \PIN_HSI~input .CFG_LVDS_IREF = 10'b0110000000;
+defparam \PIN_HSI~input .CFG_LVDS_IN_EN = 1'b0;
+defparam \PIN_HSI~input .DPCLK_DELAY = 4'b0000;
+defparam \PIN_HSI~input .OUT_DELAY = 1'b0;
+defparam \PIN_HSI~input .IN_DATA_DELAY = 3'b000;
+defparam \PIN_HSI~input .IN_REG_DELAY = 3'b000;
+
+alta_rio \PIN_OSC~input (
+	.padio(PIN_OSC),
+	.datain(gnd),
+	.oe(gnd),
+	.outclk(gnd),
+	.outclkena(vcc),
+	.inclk(gnd),
+	.inclkena(vcc),
+	.areset(gnd),
+	.sreset(gnd),
+	.combout(\PIN_OSC~input_o ),
+	.regout());
+defparam \PIN_OSC~input .coord_x = 22;
+defparam \PIN_OSC~input .coord_y = 4;
+defparam \PIN_OSC~input .coord_z = 2;
+defparam \PIN_OSC~input .IN_ASYNC_MODE = 1'b0;
+defparam \PIN_OSC~input .IN_SYNC_MODE = 1'b0;
+defparam \PIN_OSC~input .IN_POWERUP = 1'b0;
+defparam \PIN_OSC~input .OUT_REG_MODE = 1'b0;
+defparam \PIN_OSC~input .OUT_ASYNC_MODE = 1'b0;
+defparam \PIN_OSC~input .OUT_SYNC_MODE = 1'b0;
+defparam \PIN_OSC~input .OUT_POWERUP = 1'b0;
+defparam \PIN_OSC~input .OE_REG_MODE = 1'b0;
+defparam \PIN_OSC~input .OE_ASYNC_MODE = 1'b0;
+defparam \PIN_OSC~input .OE_SYNC_MODE = 1'b0;
+defparam \PIN_OSC~input .OE_POWERUP = 1'b0;
+defparam \PIN_OSC~input .CFG_TRI_INPUT = 1'b0;
+defparam \PIN_OSC~input .CFG_PULL_UP = 1'b0;
+defparam \PIN_OSC~input .CFG_SLR = 1'b0;
+defparam \PIN_OSC~input .CFG_OPEN_DRAIN = 1'b0;
+defparam \PIN_OSC~input .CFG_PDRCTRL = 4'b0010;
+defparam \PIN_OSC~input .CFG_KEEP = 2'b00;
+defparam \PIN_OSC~input .CFG_LVDS_OUT_EN = 1'b0;
+defparam \PIN_OSC~input .CFG_LVDS_SEL_CUA = 2'b00;
+defparam \PIN_OSC~input .CFG_LVDS_IREF = 10'b0110000000;
+defparam \PIN_OSC~input .CFG_LVDS_IN_EN = 1'b0;
+defparam \PIN_OSC~input .DPCLK_DELAY = 4'b0000;
+defparam \PIN_OSC~input .OUT_DELAY = 1'b0;
+defparam \PIN_OSC~input .IN_DATA_DELAY = 3'b000;
+defparam \PIN_OSC~input .IN_REG_DELAY = 3'b000;
+
+alta_slice PLL_ENABLE(
+	.A(vcc),
+	.B(vcc),
+	.C(vcc),
+	.D(\rv32.sys_ctrl_pllEnable ),
+	.Cin(),
+	.Qin(),
+	.Clk(),
+	.AsyncReset(),
+	.SyncReset(),
+	.ShiftData(),
+	.SyncLoad(),
+	.LutOut(\PLL_ENABLE~combout ),
+	.Cout(),
+	.Q());
+defparam PLL_ENABLE.coord_x = 17;
+defparam PLL_ENABLE.coord_y = 5;
+defparam PLL_ENABLE.coord_z = 4;
+defparam PLL_ENABLE.mask = 16'h00FF;
+defparam PLL_ENABLE.modeMux = 1'b0;
+defparam PLL_ENABLE.FeedbackMux = 1'b0;
+defparam PLL_ENABLE.ShiftMux = 1'b0;
+defparam PLL_ENABLE.BypassEn = 1'b0;
+defparam PLL_ENABLE.CarryEnb = 1'b1;
+
+alta_io_gclk \PLL_ENABLE~clkctrl (
+	.inclk(\PLL_ENABLE~combout ),
+	.outclk(\PLL_ENABLE~clkctrl_outclk ));
+defparam \PLL_ENABLE~clkctrl .coord_x = 22;
+defparam \PLL_ENABLE~clkctrl .coord_y = 4;
+defparam \PLL_ENABLE~clkctrl .coord_z = 4;
+
+alta_slice PLL_LOCK(
+	.A(vcc),
+	.B(vcc),
+	.C(\pll_inst|auto_generated|pll_lock_sync~q ),
+	.D(\auto_generated_inst.hbo_13_a07d11f4c42b3d12_bp ),
+	.Cin(),
+	.Qin(),
+	.Clk(),
+	.AsyncReset(),
+	.SyncReset(),
+	.ShiftData(),
+	.SyncLoad(),
+	.LutOut(\PLL_LOCK~combout ),
+	.Cout(),
+	.Q());
+defparam PLL_LOCK.coord_x = 19;
+defparam PLL_LOCK.coord_y = 5;
+defparam PLL_LOCK.coord_z = 7;
+defparam PLL_LOCK.mask = 16'hF000;
+defparam PLL_LOCK.modeMux = 1'b0;
+defparam PLL_LOCK.FeedbackMux = 1'b0;
+defparam PLL_LOCK.ShiftMux = 1'b0;
+defparam PLL_LOCK.BypassEn = 1'b0;
+defparam PLL_LOCK.CarryEnb = 1'b1;
+
+alta_asyncctrl asyncreset_ctrl_X47_Y1_N0(
+	.Din(\PLL_ENABLE~clkctrl_outclk ),
+	.Dout(\PLL_ENABLE~clkctrl_outclk__AsyncReset_X47_Y1_SIG ));
+defparam asyncreset_ctrl_X47_Y1_N0.coord_x = 19;
+defparam asyncreset_ctrl_X47_Y1_N0.coord_y = 5;
+defparam asyncreset_ctrl_X47_Y1_N0.coord_z = 0;
+defparam asyncreset_ctrl_X47_Y1_N0.AsyncCtrlMux = 2'b10;
+
+alta_clkenctrl clken_ctrl_X47_Y1_N0(
+	.ClkIn(\auto_generated_inst.hbo_13_a07d11f4c42b3d12_bp ),
+	.ClkEn(),
+	.ClkOut(\auto_generated_inst.hbo_13_a07d11f4c42b3d12_bp_X47_Y1_SIG_VCC ));
+defparam clken_ctrl_X47_Y1_N0.coord_x = 19;
+defparam clken_ctrl_X47_Y1_N0.coord_y = 5;
+defparam clken_ctrl_X47_Y1_N0.coord_z = 0;
+defparam clken_ctrl_X47_Y1_N0.ClkMux = 2'b10;
+defparam clken_ctrl_X47_Y1_N0.ClkEnMux = 2'b01;
+
+alta_io_gclk \gclksw_inst|gclk_switch (
+	.inclk(\gclksw_inst|gclk_switch__alta_gclksw__clkout ),
+	.outclk(\auto_generated_inst.hbo_22_f9ff3d300b43c0f2_bp ));
+defparam \gclksw_inst|gclk_switch .coord_x = 22;
+defparam \gclksw_inst|gclk_switch .coord_y = 4;
+defparam \gclksw_inst|gclk_switch .coord_z = 5;
+
+alta_gclksw \gclksw_inst|gclk_switch__alta_gclksw (
+	.resetn(\rv32.resetn_out ),
+	.clkin0(\PIN_HSI~input_o ),
+	.clkin1(\PIN_HSE~input_o ),
+	.clkin2(\pll_inst|auto_generated|pll1_CLK_bus [0]),
+	.clkin3(vcc),
+	.select({\rv32.sys_ctrl_clkSource[1] , \rv32.sys_ctrl_clkSource[0] }),
+	.clkout(\gclksw_inst|gclk_switch__alta_gclksw__clkout ));
+defparam \gclksw_inst|gclk_switch__alta_gclksw .coord_x = 22;
+defparam \gclksw_inst|gclk_switch__alta_gclksw .coord_y = 4;
+defparam \gclksw_inst|gclk_switch__alta_gclksw .coord_z = 0;
+
+alta_pllve \pll_inst|auto_generated|pll1 (
+	.clkin(\PIN_HSE~input_o ),
+	.clkfb(\pll_inst|auto_generated|pll1~FBOUT ),
+	.pfden(vcc),
+	.resetn(!\PLL_ENABLE~combout ),
+	.phasecounterselect({gnd, gnd, gnd}),
+	.phaseupdown(gnd),
+	.phasestep(gnd),
+	.scanclk(gnd),
+	.scanclkena(vcc),
+	.scandata(gnd),
+	.configupdate(gnd),
+	.scandataout(),
+	.scandone(),
+	.phasedone(),
+	.clkout0(\pll_inst|auto_generated|pll1_CLK_bus [0]),
+	.clkout1(\pll_inst|auto_generated|pll1_CLK_bus [1]),
+	.clkout2(\pll_inst|auto_generated|pll1_CLK_bus [2]),
+	.clkout3(\pll_inst|auto_generated|pll1_CLK_bus [3]),
+	.clkout4(\pll_inst|auto_generated|pll1_CLK_bus [4]),
+	.clkfbout(\pll_inst|auto_generated|pll1~FBOUT ),
+	.lock(\auto_generated_inst.hbo_13_a07d11f4c42b3d12_bp ));
+defparam \pll_inst|auto_generated|pll1 .coord_x = 22;
+defparam \pll_inst|auto_generated|pll1 .coord_y = 5;
+defparam \pll_inst|auto_generated|pll1 .coord_z = 0;
+defparam \pll_inst|auto_generated|pll1 .CLKIN_HIGH = 8'b11111111;
+defparam \pll_inst|auto_generated|pll1 .CLKIN_LOW = 8'b11111111;
+defparam \pll_inst|auto_generated|pll1 .CLKIN_TRIM = 1'b0;
+defparam \pll_inst|auto_generated|pll1 .CLKIN_BYPASS = 1'b1;
+defparam \pll_inst|auto_generated|pll1 .CLKFB_HIGH = 8'b00011101;
+defparam \pll_inst|auto_generated|pll1 .CLKFB_LOW = 8'b00011101;
+defparam \pll_inst|auto_generated|pll1 .CLKFB_TRIM = 1'b0;
+defparam \pll_inst|auto_generated|pll1 .CLKFB_BYPASS = 1'b0;
+defparam \pll_inst|auto_generated|pll1 .CLKDIV0_EN = 1'b1;
+defparam \pll_inst|auto_generated|pll1 .CLKDIV1_EN = 1'b0;
+defparam \pll_inst|auto_generated|pll1 .CLKDIV2_EN = 1'b0;
+defparam \pll_inst|auto_generated|pll1 .CLKDIV3_EN = 1'b0;
+defparam \pll_inst|auto_generated|pll1 .CLKDIV4_EN = 1'b0;
+defparam \pll_inst|auto_generated|pll1 .CLKOUT0_HIGH = 8'b00000001;
+defparam \pll_inst|auto_generated|pll1 .CLKOUT0_LOW = 8'b00000001;
+defparam \pll_inst|auto_generated|pll1 .CLKOUT0_TRIM = 1'b0;
+defparam \pll_inst|auto_generated|pll1 .CLKOUT0_BYPASS = 1'b0;
+defparam \pll_inst|auto_generated|pll1 .CLKOUT1_HIGH = 8'b11111111;
+defparam \pll_inst|auto_generated|pll1 .CLKOUT1_LOW = 8'b11111111;
+defparam \pll_inst|auto_generated|pll1 .CLKOUT1_TRIM = 1'b0;
+defparam \pll_inst|auto_generated|pll1 .CLKOUT1_BYPASS = 1'b0;
+defparam \pll_inst|auto_generated|pll1 .CLKOUT2_HIGH = 8'b11111111;
+defparam \pll_inst|auto_generated|pll1 .CLKOUT2_LOW = 8'b11111111;
+defparam \pll_inst|auto_generated|pll1 .CLKOUT2_TRIM = 1'b0;
+defparam \pll_inst|auto_generated|pll1 .CLKOUT2_BYPASS = 1'b0;
+defparam \pll_inst|auto_generated|pll1 .CLKOUT3_HIGH = 8'b11111111;
+defparam \pll_inst|auto_generated|pll1 .CLKOUT3_LOW = 8'b11111111;
+defparam \pll_inst|auto_generated|pll1 .CLKOUT3_TRIM = 1'b0;
+defparam \pll_inst|auto_generated|pll1 .CLKOUT3_BYPASS = 1'b0;
+defparam \pll_inst|auto_generated|pll1 .CLKOUT4_HIGH = 8'b11111111;
+defparam \pll_inst|auto_generated|pll1 .CLKOUT4_LOW = 8'b11111111;
+defparam \pll_inst|auto_generated|pll1 .CLKOUT4_TRIM = 1'b0;
+defparam \pll_inst|auto_generated|pll1 .CLKOUT4_BYPASS = 1'b0;
+defparam \pll_inst|auto_generated|pll1 .CLKOUT0_DEL = 8'b00000000;
+defparam \pll_inst|auto_generated|pll1 .CLKOUT1_DEL = 8'b00000000;
+defparam \pll_inst|auto_generated|pll1 .CLKOUT2_DEL = 8'b00000000;
+defparam \pll_inst|auto_generated|pll1 .CLKOUT3_DEL = 8'b00000000;
+defparam \pll_inst|auto_generated|pll1 .CLKOUT4_DEL = 8'b00000000;
+defparam \pll_inst|auto_generated|pll1 .CLKOUT0_PHASE = 3'b000;
+defparam \pll_inst|auto_generated|pll1 .CLKOUT1_PHASE = 3'b000;
+defparam \pll_inst|auto_generated|pll1 .CLKOUT2_PHASE = 3'b000;
+defparam \pll_inst|auto_generated|pll1 .CLKOUT3_PHASE = 3'b000;
+defparam \pll_inst|auto_generated|pll1 .CLKOUT4_PHASE = 3'b000;
+defparam \pll_inst|auto_generated|pll1 .CLKFB_DEL = 8'b00000000;
+defparam \pll_inst|auto_generated|pll1 .CLKFB_PHASE = 3'b000;
+defparam \pll_inst|auto_generated|pll1 .FEEDBACK_MODE = 3'b100;
+defparam \pll_inst|auto_generated|pll1 .FBDELAY_VAL = 3'b100;
+defparam \pll_inst|auto_generated|pll1 .PLLOUTP_EN = 1'b0;
+defparam \pll_inst|auto_generated|pll1 .PLLOUTN_EN = 1'b0;
+defparam \pll_inst|auto_generated|pll1 .CLKOUT1_CASCADE = 1'b0;
+defparam \pll_inst|auto_generated|pll1 .CLKOUT2_CASCADE = 1'b0;
+defparam \pll_inst|auto_generated|pll1 .CLKOUT3_CASCADE = 1'b0;
+defparam \pll_inst|auto_generated|pll1 .CLKOUT4_CASCADE = 1'b0;
+defparam \pll_inst|auto_generated|pll1 .VCO_POST_DIV = 1'b1;
+defparam \pll_inst|auto_generated|pll1 .REG_CTRL = 2'b00;
+defparam \pll_inst|auto_generated|pll1 .CP = 3'b100;
+defparam \pll_inst|auto_generated|pll1 .RREF = 2'b01;
+defparam \pll_inst|auto_generated|pll1 .RVI = 2'b01;
+defparam \pll_inst|auto_generated|pll1 .IVCO = 3'b010;
+defparam \pll_inst|auto_generated|pll1 .PLL_EN_FLAG = 1'b1;
+
+alta_slice \pll_inst|auto_generated|pll_lock_sync (
+	.A(vcc),
+	.B(vcc),
+	.C(vcc),
+	.D(vcc),
+	.Cin(),
+	.Qin(\pll_inst|auto_generated|pll_lock_sync~q ),
+	.Clk(\auto_generated_inst.hbo_13_a07d11f4c42b3d12_bp_X47_Y1_SIG_VCC ),
+	.AsyncReset(\PLL_ENABLE~clkctrl_outclk__AsyncReset_X47_Y1_SIG ),
+	.SyncReset(),
+	.ShiftData(),
+	.SyncLoad(),
+	.LutOut(\pll_inst|auto_generated|pll_lock_sync~feeder_combout ),
+	.Cout(),
+	.Q(\pll_inst|auto_generated|pll_lock_sync~q ));
+defparam \pll_inst|auto_generated|pll_lock_sync .coord_x = 19;
+defparam \pll_inst|auto_generated|pll_lock_sync .coord_y = 5;
+defparam \pll_inst|auto_generated|pll_lock_sync .coord_z = 6;
+defparam \pll_inst|auto_generated|pll_lock_sync .mask = 16'hFFFF;
+defparam \pll_inst|auto_generated|pll_lock_sync .modeMux = 1'b0;
+defparam \pll_inst|auto_generated|pll_lock_sync .FeedbackMux = 1'b0;
+defparam \pll_inst|auto_generated|pll_lock_sync .ShiftMux = 1'b0;
+defparam \pll_inst|auto_generated|pll_lock_sync .BypassEn = 1'b0;
+defparam \pll_inst|auto_generated|pll_lock_sync .CarryEnb = 1'b1;
+
+alta_rv32 rv32(
+	.sys_clk(\gclksw_inst|gclk_switch__alta_gclksw__clkout ),
+	.mem_ahb_hready(\rv32.mem_ahb_hready ),
+	.mem_ahb_hreadyout(vcc),
+	.mem_ahb_htrans({\rv32.mem_ahb_htrans[1] , \rv32.mem_ahb_htrans[0] }),
+	.mem_ahb_hsize({\rv32.mem_ahb_hsize[2] , \rv32.mem_ahb_hsize[1] , \rv32.mem_ahb_hsize[0] }),
+	.mem_ahb_hburst({\rv32.mem_ahb_hburst[2] , \rv32.mem_ahb_hburst[1] , \rv32.mem_ahb_hburst[0] }),
+	.mem_ahb_hwrite(\rv32.mem_ahb_hwrite ),
+	.mem_ahb_haddr({\rv32.mem_ahb_haddr[31] , \rv32.mem_ahb_haddr[30] , \rv32.mem_ahb_haddr[29] , \rv32.mem_ahb_haddr[28] , \rv32.mem_ahb_haddr[27] , \rv32.mem_ahb_haddr[26] , \rv32.mem_ahb_haddr[25] , \rv32.mem_ahb_haddr[24] , \rv32.mem_ahb_haddr[23] , \rv32.mem_ahb_haddr[22] , \rv32.mem_ahb_haddr[21] , \rv32.mem_ahb_haddr[20] , \rv32.mem_ahb_haddr[19] , \rv32.mem_ahb_haddr[18] , \rv32.mem_ahb_haddr[17] , \rv32.mem_ahb_haddr[16] , \rv32.mem_ahb_haddr[15] , \rv32.mem_ahb_haddr[14] , \rv32.mem_ahb_haddr[13] , \rv32.mem_ahb_haddr[12] , \rv32.mem_ahb_haddr[11] , \rv32.mem_ahb_haddr[10] , \rv32.mem_ahb_haddr[9] , \rv32.mem_ahb_haddr[8] , \rv32.mem_ahb_haddr[7] , \rv32.mem_ahb_haddr[6] , \rv32.mem_ahb_haddr[5] , \rv32.mem_ahb_haddr[4] , \rv32.mem_ahb_haddr[3] , \rv32.mem_ahb_haddr[2] , \rv32.mem_ahb_haddr[1] , \rv32.mem_ahb_haddr[0] }),
+	.mem_ahb_hwdata({\rv32.mem_ahb_hwdata[31] , \rv32.mem_ahb_hwdata[30] , \rv32.mem_ahb_hwdata[29] , \rv32.mem_ahb_hwdata[28] , \rv32.mem_ahb_hwdata[27] , \rv32.mem_ahb_hwdata[26] , \rv32.mem_ahb_hwdata[25] , \rv32.mem_ahb_hwdata[24] , \rv32.mem_ahb_hwdata[23] , \rv32.mem_ahb_hwdata[22] , \rv32.mem_ahb_hwdata[21] , \rv32.mem_ahb_hwdata[20] , \rv32.mem_ahb_hwdata[19] , \rv32.mem_ahb_hwdata[18] , \rv32.mem_ahb_hwdata[17] , \rv32.mem_ahb_hwdata[16] , \rv32.mem_ahb_hwdata[15] , \rv32.mem_ahb_hwdata[14] , \rv32.mem_ahb_hwdata[13] , \rv32.mem_ahb_hwdata[12] , \rv32.mem_ahb_hwdata[11] , \rv32.mem_ahb_hwdata[10] , \rv32.mem_ahb_hwdata[9] , \rv32.mem_ahb_hwdata[8] , \rv32.mem_ahb_hwdata[7] , \rv32.mem_ahb_hwdata[6] , \rv32.mem_ahb_hwdata[5] , \rv32.mem_ahb_hwdata[4] , \rv32.mem_ahb_hwdata[3] , \rv32.mem_ahb_hwdata[2] , \rv32.mem_ahb_hwdata[1] , \rv32.mem_ahb_hwdata[0] }),
+	.mem_ahb_hresp(gnd),
+	.mem_ahb_hrdata({gnd, gnd, gnd, gnd, gnd, gnd, gnd, gnd, gnd, gnd, gnd, gnd, gnd, gnd, gnd, gnd, gnd, gnd, gnd, gnd, gnd, gnd, gnd, gnd, gnd, gnd, gnd, gnd, gnd, gnd, gnd, gnd}),
+	.slave_ahb_hsel(gnd),
+	.slave_ahb_hready(vcc),
+	.slave_ahb_hreadyout(\rv32.slave_ahb_hreadyout ),
+	.slave_ahb_htrans({gnd, gnd}),
+	.slave_ahb_hsize({gnd, gnd, gnd}),
+	.slave_ahb_hburst({gnd, gnd, gnd}),
+	.slave_ahb_hwrite(gnd),
+	.slave_ahb_haddr({gnd, gnd, gnd, gnd, gnd, gnd, gnd, gnd, gnd, gnd, gnd, gnd, gnd, gnd, gnd, gnd, gnd, gnd, gnd, gnd, gnd, gnd, gnd, gnd, gnd, gnd, gnd, gnd, gnd, gnd, gnd, gnd}),
+	.slave_ahb_hwdata({gnd, gnd, gnd, gnd, gnd, gnd, gnd, gnd, gnd, gnd, gnd, gnd, gnd, gnd, gnd, gnd, gnd, gnd, gnd, gnd, gnd, gnd, gnd, gnd, gnd, gnd, gnd, gnd, gnd, gnd, gnd, gnd}),
+	.slave_ahb_hresp(\rv32.slave_ahb_hresp ),
+	.slave_ahb_hrdata({\rv32.slave_ahb_hrdata[31] , \rv32.slave_ahb_hrdata[30] , \rv32.slave_ahb_hrdata[29] , \rv32.slave_ahb_hrdata[28] , \rv32.slave_ahb_hrdata[27] , \rv32.slave_ahb_hrdata[26] , \rv32.slave_ahb_hrdata[25] , \rv32.slave_ahb_hrdata[24] , \rv32.slave_ahb_hrdata[23] , \rv32.slave_ahb_hrdata[22] , \rv32.slave_ahb_hrdata[21] , \rv32.slave_ahb_hrdata[20] , \rv32.slave_ahb_hrdata[19] , \rv32.slave_ahb_hrdata[18] , \rv32.slave_ahb_hrdata[17] , \rv32.slave_ahb_hrdata[16] , \rv32.slave_ahb_hrdata[15] , \rv32.slave_ahb_hrdata[14] , \rv32.slave_ahb_hrdata[13] , \rv32.slave_ahb_hrdata[12] , \rv32.slave_ahb_hrdata[11] , \rv32.slave_ahb_hrdata[10] , \rv32.slave_ahb_hrdata[9] , \rv32.slave_ahb_hrdata[8] , \rv32.slave_ahb_hrdata[7] , \rv32.slave_ahb_hrdata[6] , \rv32.slave_ahb_hrdata[5] , \rv32.slave_ahb_hrdata[4] , \rv32.slave_ahb_hrdata[3] , \rv32.slave_ahb_hrdata[2] , \rv32.slave_ahb_hrdata[1] , \rv32.slave_ahb_hrdata[0] }),
+	.gpio0_io_in({gnd, gnd, gnd, gnd, gnd, gnd, gnd, gnd}),
+	.gpio0_io_out_data({\rv32.gpio0_io_out_data[7] , \rv32.gpio0_io_out_data[6] , \rv32.gpio0_io_out_data[5] , \rv32.gpio0_io_out_data[4] , \rv32.gpio0_io_out_data[3] , \rv32.gpio0_io_out_data[2] , \rv32.gpio0_io_out_data[1] , \rv32.gpio0_io_out_data[0] }),
+	.gpio0_io_out_en({\rv32.gpio0_io_out_en[7] , \rv32.gpio0_io_out_en[6] , \rv32.gpio0_io_out_en[5] , \rv32.gpio0_io_out_en[4] , \rv32.gpio0_io_out_en[3] , \rv32.gpio0_io_out_en[2] , \rv32.gpio0_io_out_en[1] , \rv32.gpio0_io_out_en[0] }),
+	.gpio1_io_in({gnd, \PIN_88~input_o , \PIN_91~input_o , \PIN_92~input_o , \PIN_1~input_o , gnd, \PIN_3~input_o , \PIN_2~input_o }),
+	.gpio1_io_out_data({\rv32.gpio1_io_out_data[7] , \rv32.gpio1_io_out_data[6] , \rv32.gpio1_io_out_data[5] , \rv32.gpio1_io_out_data[4] , \rv32.gpio1_io_out_data[3] , \rv32.gpio1_io_out_data[2] , \rv32.gpio1_io_out_data[1] , \rv32.gpio1_io_out_data[0] }),
+	.gpio1_io_out_en({\rv32.gpio1_io_out_en[7] , \rv32.gpio1_io_out_en[6] , \rv32.gpio1_io_out_en[5] , \rv32.gpio1_io_out_en[4] , \rv32.gpio1_io_out_en[3] , \rv32.gpio1_io_out_en[2] , \rv32.gpio1_io_out_en[1] , \rv32.gpio1_io_out_en[0] }),
+	.sys_ctrl_clkSource({\rv32.sys_ctrl_clkSource[1] , \rv32.sys_ctrl_clkSource[0] }),
+	.sys_ctrl_hseEnable(\rv32.sys_ctrl_hseEnable ),
+	.sys_ctrl_hseBypass(\rv32.sys_ctrl_hseBypass ),
+	.sys_ctrl_pllEnable(\rv32.sys_ctrl_pllEnable ),
+	.sys_ctrl_pllReady(\auto_generated_inst.hbo_13_a07d11f4c42b3d12_bp ),
+	.sys_ctrl_sleep(\rv32.sys_ctrl_sleep ),
+	.sys_ctrl_stop(\rv32.sys_ctrl_stop ),
+	.sys_ctrl_standby(\rv32.sys_ctrl_standby ),
+	.gpio2_io_in({gnd, gnd, gnd, gnd, gnd, \PIN_96~input_o , \PIN_95~input_o , \PIN_97~input_o }),
+	.gpio2_io_out_data({\rv32.gpio2_io_out_data[7] , \rv32.gpio2_io_out_data[6] , \rv32.gpio2_io_out_data[5] , \rv32.gpio2_io_out_data[4] , \rv32.gpio2_io_out_data[3] , \rv32.gpio2_io_out_data[2] , \rv32.gpio2_io_out_data[1] , \rv32.gpio2_io_out_data[0] }),
+	.gpio2_io_out_en({\rv32.gpio2_io_out_en[7] , \rv32.gpio2_io_out_en[6] , \rv32.gpio2_io_out_en[5] , \rv32.gpio2_io_out_en[4] , \rv32.gpio2_io_out_en[3] , \rv32.gpio2_io_out_en[2] , \rv32.gpio2_io_out_en[1] , \rv32.gpio2_io_out_en[0] }),
+	.gpio3_io_in({gnd, gnd, gnd, gnd, gnd, gnd, gnd, gnd}),
+	.gpio3_io_out_data({\rv32.gpio3_io_out_data[7] , \rv32.gpio3_io_out_data[6] , \rv32.gpio3_io_out_data[5] , \rv32.gpio3_io_out_data[4] , \rv32.gpio3_io_out_data[3] , \rv32.gpio3_io_out_data[2] , \rv32.gpio3_io_out_data[1] , \rv32.gpio3_io_out_data[0] }),
+	.gpio3_io_out_en({\rv32.gpio3_io_out_en[7] , \rv32.gpio3_io_out_en[6] , \rv32.gpio3_io_out_en[5] , \rv32.gpio3_io_out_en[4] , \rv32.gpio3_io_out_en[3] , \rv32.gpio3_io_out_en[2] , \rv32.gpio3_io_out_en[1] , \rv32.gpio3_io_out_en[0] }),
+	.gpio4_io_in({gnd, gnd, gnd, gnd, gnd, gnd, gnd, gnd}),
+	.gpio4_io_out_data({\rv32.gpio4_io_out_data[7] , \rv32.gpio4_io_out_data[6] , \rv32.gpio4_io_out_data[5] , \rv32.gpio4_io_out_data[4] , \rv32.gpio4_io_out_data[3] , \rv32.gpio4_io_out_data[2] , \rv32.gpio4_io_out_data[1] , \rv32.gpio4_io_out_data[0] }),
+	.gpio4_io_out_en({\rv32.gpio4_io_out_en[7] , \rv32.gpio4_io_out_en[6] , \rv32.gpio4_io_out_en[5] , \rv32.gpio4_io_out_en[4] , \rv32.gpio4_io_out_en[3] , \rv32.gpio4_io_out_en[2] , \rv32.gpio4_io_out_en[1] , \rv32.gpio4_io_out_en[0] }),
+	.gpio5_io_in({gnd, gnd, gnd, gnd, gnd, gnd, gnd, gnd}),
+	.gpio5_io_out_data({\rv32.gpio5_io_out_data[7] , \rv32.gpio5_io_out_data[6] , \rv32.gpio5_io_out_data[5] , \rv32.gpio5_io_out_data[4] , \rv32.gpio5_io_out_data[3] , \rv32.gpio5_io_out_data[2] , \rv32.gpio5_io_out_data[1] , \rv32.gpio5_io_out_data[0] }),
+	.gpio5_io_out_en({\rv32.gpio5_io_out_en[7] , \rv32.gpio5_io_out_en[6] , \rv32.gpio5_io_out_en[5] , \rv32.gpio5_io_out_en[4] , \rv32.gpio5_io_out_en[3] , \rv32.gpio5_io_out_en[2] , \rv32.gpio5_io_out_en[1] , \rv32.gpio5_io_out_en[0] }),
+	.gpio6_io_in({gnd, gnd, gnd, gnd, gnd, gnd, \PIN_69~input_o , gnd}),
+	.gpio6_io_out_data({\rv32.gpio6_io_out_data[7] , \rv32.gpio6_io_out_data[6] , \rv32.gpio6_io_out_data[5] , \rv32.gpio6_io_out_data[4] , \rv32.gpio6_io_out_data[3] , \rv32.gpio6_io_out_data[2] , \rv32.gpio6_io_out_data[1] , \rv32.gpio6_io_out_data[0] }),
+	.gpio6_io_out_en({\rv32.gpio6_io_out_en[7] , \rv32.gpio6_io_out_en[6] , \rv32.gpio6_io_out_en[5] , \rv32.gpio6_io_out_en[4] , \rv32.gpio6_io_out_en[3] , \rv32.gpio6_io_out_en[2] , \rv32.gpio6_io_out_en[1] , \rv32.gpio6_io_out_en[0] }),
+	.gpio7_io_in({gnd, gnd, gnd, gnd, gnd, gnd, gnd, gnd}),
+	.gpio7_io_out_data({\rv32.gpio7_io_out_data[7] , \rv32.gpio7_io_out_data[6] , \rv32.gpio7_io_out_data[5] , \rv32.gpio7_io_out_data[4] , \rv32.gpio7_io_out_data[3] , \rv32.gpio7_io_out_data[2] , \rv32.gpio7_io_out_data[1] , \rv32.gpio7_io_out_data[0] }),
+	.gpio7_io_out_en({\rv32.gpio7_io_out_en[7] , \rv32.gpio7_io_out_en[6] , \rv32.gpio7_io_out_en[5] , \rv32.gpio7_io_out_en[4] , \rv32.gpio7_io_out_en[3] , \rv32.gpio7_io_out_en[2] , \rv32.gpio7_io_out_en[1] , \rv32.gpio7_io_out_en[0] }),
+	.gpio8_io_in({gnd, gnd, gnd, gnd, gnd, gnd, gnd, gnd}),
+	.gpio8_io_out_data({\rv32.gpio8_io_out_data[7] , \rv32.gpio8_io_out_data[6] , \rv32.gpio8_io_out_data[5] , \rv32.gpio8_io_out_data[4] , \rv32.gpio8_io_out_data[3] , \rv32.gpio8_io_out_data[2] , \rv32.gpio8_io_out_data[1] , \rv32.gpio8_io_out_data[0] }),
+	.gpio8_io_out_en({\rv32.gpio8_io_out_en[7] , \rv32.gpio8_io_out_en[6] , \rv32.gpio8_io_out_en[5] , \rv32.gpio8_io_out_en[4] , \rv32.gpio8_io_out_en[3] , \rv32.gpio8_io_out_en[2] , \rv32.gpio8_io_out_en[1] , \rv32.gpio8_io_out_en[0] }),
+	.gpio9_io_in({gnd, gnd, gnd, gnd, gnd, gnd, gnd, gnd}),
+	.gpio9_io_out_data({\rv32.gpio9_io_out_data[7] , \rv32.gpio9_io_out_data[6] , \rv32.gpio9_io_out_data[5] , \rv32.gpio9_io_out_data[4] , \rv32.gpio9_io_out_data[3] , \rv32.gpio9_io_out_data[2] , \rv32.gpio9_io_out_data[1] , \rv32.gpio9_io_out_data[0] }),
+	.gpio9_io_out_en({\rv32.gpio9_io_out_en[7] , \rv32.gpio9_io_out_en[6] , \rv32.gpio9_io_out_en[5] , \rv32.gpio9_io_out_en[4] , \rv32.gpio9_io_out_en[3] , \rv32.gpio9_io_out_en[2] , \rv32.gpio9_io_out_en[1] , \rv32.gpio9_io_out_en[0] }),
+	.ext_resetn(vcc),
+	.resetn_out(\rv32.resetn_out ),
+	.dmactive(\rv32.dmactive ),
+	.swj_JTAGNSW(\rv32.swj_JTAGNSW ),
+	.swj_JTAGSTATE({\rv32.swj_JTAGSTATE[3] , \rv32.swj_JTAGSTATE[2] , \rv32.swj_JTAGSTATE[1] , \rv32.swj_JTAGSTATE[0] }),
+	.swj_JTAGIR({\rv32.swj_JTAGIR[3] , \rv32.swj_JTAGIR[2] , \rv32.swj_JTAGIR[1] , \rv32.swj_JTAGIR[0] }),
+	.ext_int({gnd, gnd, gnd, gnd, gnd, gnd, gnd, gnd}),
+	.ext_dma_DMACBREQ({gnd, gnd, gnd, gnd}),
+	.ext_dma_DMACLBREQ({gnd, gnd, gnd, gnd}),
+	.ext_dma_DMACSREQ({gnd, gnd, gnd, gnd}),
+	.ext_dma_DMACLSREQ({gnd, gnd, gnd, gnd}),
+	.ext_dma_DMACCLR({\rv32.ext_dma_DMACCLR[3] , \rv32.ext_dma_DMACCLR[2] , \rv32.ext_dma_DMACCLR[1] , \rv32.ext_dma_DMACCLR[0] }),
+	.ext_dma_DMACTC({\rv32.ext_dma_DMACTC[3] , \rv32.ext_dma_DMACTC[2] , \rv32.ext_dma_DMACTC[1] , \rv32.ext_dma_DMACTC[0] }),
+	.local_int({gnd, gnd, gnd, gnd}),
+	.test_mode({gnd, gnd}),
+	.usb0_xcvr_clk(gnd),
+	.usb0_id(vcc));
+defparam rv32.coord_x = 0;
+defparam rv32.coord_y = 5;
+defparam rv32.coord_z = 0;
+
+endmodule

+ 367 - 0
logic/logic_log.txt

@@ -0,0 +1,367 @@
+> set sh_continue_on_error false
+> set sh_echo_on_source  true
+> set sh_quiet_on_source true
+> set cc_critical_as_fatal true
+> 
+> set_seed_rand 10
+> if { ! [info exists LOGIC_DEVICE] } {
+  set LOGIC_DEVICE AGRV2KL100
+}
+> if { ! [info exists LOGIC_DESIGN] } {
+  set LOGIC_DESIGN top
+}
+> if { ! [info exists LOGIC_MODULE] } {
+  set LOGIC_MODULE top
+}
+> if { ! [info exists IP_INSTALL_DIR] } {
+  set IP_INSTALL_DIR ""
+}
+> if { ! [info exists LOGIC_DIR] } {
+  set LOGIC_DIR .
+}
+> if { ! [info exists LOGIC_VV] } {
+  set LOGIC_VV "${LOGIC_DESIGN}.v"
+}
+> if { ! [info exists IP_VV] } {
+  set IP_VV ""
+}
+> if { ! [info exists LOGIC_ASF] } {
+  set LOGIC_ASF ""
+}
+> if { ! [info exists LOGIC_PRE] } {
+  set LOGIC_PRE ""
+}
+> if { ! [info exists LOGIC_POST] } {
+  set LOGIC_POST ""
+}
+> if { ! [info exists LOGIC_FORCE] } {
+  set LOGIC_FORCE false
+}
+> if { ! [info exists LOGIC_COMPRESS] } {
+  set LOGIC_COMPRESS false
+}
+> 
+> cd $LOGIC_DIR
+> 
+> alta::set_verbose_cmd false
+> set logic_qsf ${LOGIC_DESIGN}.qsf
+> set skip_setup false
+> if { [file exists $logic_qsf] } {
+  if { $LOGIC_FORCE } {
+    alta::tcl_info "Overwrite existing LOGIC preparation files in $LOGIC_DIR"
+  } else {
+    alta::tcl_warn "Files for LOGIC preparation already exist in $LOGIC_DIR, will not overwrite"
+    set skip_setup true
+  }
+}
+Warn: Files for LOGIC preparation already exist in logic, will not overwrite.
+> set logic_ip false
+> if { $IP_INSTALL_DIR != "" } {
+  set logic_ip true
+}
+> 
+> set ETC_DIR [file join [alta::prog_home] "etc"]
+> set IP_FILES ""
+> set VERILOG_FILES $LOGIC_VV
+> if { $IP_VV != "" } {
+  set VERILOG_FILES "$VERILOG_FILES $IP_VV"
+}
+> set VQM_FILES ""
+> set VHDL_FILES ""
+> set AF_QUARTUS_TEMPL [file join $ETC_DIR "af_quartus.tcl"]
+> set AF_QUARTUS "af_quartus.tcl"
+> set AF_IP_TEMPL [file join $ETC_DIR "af_ip.tcl"]
+> set AF_IP "af_ip.tcl"
+> set AF_MAP_TEMPL ""
+> set AF_MAP ""
+> set AF_RUN_TEMPL [file join $ETC_DIR "af_run.tcl"]
+> set AF_RUN "af_run.tcl"
+> set AF_BATCH_TEMPL ""
+> set AF_BATCH ""
+> set VE_FILE ""
+> 
+> if { ! [info exists ORIGINAL_DIR] } {
+  set ORIGINAL_DIR ""
+}
+> if { ! [info exists ORIGINAL_OUTPUT] } {
+  set ORIGINAL_OUTPUT ""
+}
+> if { ! [info exists ORIGINAL_QSF] } {
+  set ORIGINAL_QSF ""
+}
+> if { ! [info exists ORIGINAL_PIN] } {
+  set ORIGINAL_PIN ""
+}
+> 
+> set GCLK_CNT -1; # Allow an extra gclk for GCLKSW
+> set USE_DESIGN_TEMPL true
+> 
+> set logic_hx ${LOGIC_DESIGN}.hx
+> set hx_fp [open $logic_hx r]
+> set hsi_freq 0
+> set hse_freq 0
+> set sys_freq 0
+> set bus_freq 0
+> while { [gets $hx_fp line] >= 0 } {
+  set words [split $line]
+  if { [lindex $words 0] == "#define" } {
+    if { [lindex $words 1] == "BOARD_HSI_FREQUENCY" } {
+      set hsi_freq [lindex $words 2]
+    } elseif { [lindex $words 1] == "BOARD_HSE_FREQUENCY" } {
+      set hse_freq [lindex $words 2]
+    } elseif { [lindex $words 1] == "BOARD_PLL_FREQUENCY" } {
+      set sys_freq [lindex $words 2]
+    } elseif { [lindex $words 1] == "BOARD_BUS_FREQUENCY" } {
+      set bus_freq [lindex $words 2]
+    }
+    if { [lindex $words 1] == "BOARD_PLL_CLKIN" } {
+      set BOARD_PLL_CLKIN [lindex $words 2]
+    }
+    if { [lindex $words 1] == "USB0_MODE" } {
+      set USB0_MODE [lindex $words 2]
+    }
+  }
+}
+> close $hx_fp
+> 
+> if { ! $logic_ip } {
+  set sdc_file ${LOGIC_DESIGN}.sdc
+  set sdc_ip ""
+} else {
+  set sdc_file ${LOGIC_DESIGN}_.sdc
+  set sdc_ip ${LOGIC_DESIGN}.sdc
+}
+> 
+> if { ! $skip_setup } {
+  if { ! [file exists $sdc_file] } {
+    set sdc_fp [open $sdc_file w]
+    puts $sdc_fp "# pio_begin"
+    if { $hsi_freq != 0 } {
+      set hsi_period [expr 1000000000.0/$hsi_freq]
+      puts $sdc_fp "if { ! \[info exists ::HSI_PERIOD\] } {"
+      puts $sdc_fp "  set ::HSI_PERIOD $hsi_period"
+      puts $sdc_fp "}"
+      puts $sdc_fp "create_clock -name PIN_HSI -period \$::HSI_PERIOD \[get_ports PIN_HSI\]"
+      puts $sdc_fp "set_clock_groups -asynchronous -group PIN_HSI"
+    }
+    if { $hse_freq != 0 } {
+      set hse_period [expr 1000000000.0/$hse_freq]
+      puts $sdc_fp "if { ! \[info exists ::HSE_PERIOD\] } {"
+      puts $sdc_fp "  set ::HSE_PERIOD $hse_period"
+      puts $sdc_fp "}"
+      puts $sdc_fp "create_clock -name PIN_HSE -period \$::HSE_PERIOD \[get_ports PIN_HSE\]"
+      puts $sdc_fp "set_clock_groups -asynchronous -group PIN_HSE"
+    }
+    puts $sdc_fp "derive_pll_clocks -create_base_clocks"
+    puts $sdc_fp "# pio_end"
+    close $sdc_fp
+  }
+
+  if { $sdc_ip != "" && ! [file exists $sdc_ip] } {
+    set sdc_fp [open $sdc_ip w]
+    puts $sdc_fp "# pio_begin"
+    if { $sys_freq != 0 } {
+      set sys_period [expr 1000000000.0/$sys_freq]
+      puts $sdc_fp "create_clock -name sys_clock -period $sys_period \[get_ports sys_clock\]"
+    }
+    if { $bus_freq != 0 } {
+      set bus_period [expr 1000000000.0/$bus_freq]
+      puts $sdc_fp "create_clock -name bus_clock -period $bus_period \[get_ports bus_clock\]"
+    }
+    puts $sdc_fp "# pio_end"
+    close $sdc_fp
+  }
+
+  load_architect -no_route -type $LOGIC_DEVICE
+
+  alta::setupRun ${LOGIC_DESIGN} ${LOGIC_MODULE} \
+                 "${IP_FILES}" \
+                 "${VERILOG_FILES}" \
+                 "${VQM_FILES}" \
+                 "${VHDL_FILES}"\
+                 "${AF_QUARTUS_TEMPL}" "${AF_QUARTUS}"\
+                 "${AF_IP_TEMPL}" "${AF_IP}" \
+                 "${AF_MAP_TEMPL}" "${AF_MAP}" \
+                 "${AF_RUN_TEMPL}" "${AF_RUN}" \
+                 "${AF_BATCH_TEMPL}" "${AF_BATCH}" \
+                 "${VE_FILE}" \
+                 "." "${ORIGINAL_DIR}" "${ORIGINAL_OUTPUT}"\
+                 "${ORIGINAL_QSF}" "${ORIGINAL_PIN}" \
+                 "${GCLK_CNT}" "${USE_DESIGN_TEMPL}"
+
+  if { $logic_ip } {
+    set qsf_fp [open $logic_qsf]
+    set qsf_lines {}
+    set is_pio false
+    while { [gets $qsf_fp line] >= 0 } {
+      if { [string first "pio_begin" $line] >= 0 } {
+        set is_pio true
+      } elseif { [string first "pio_end" $line] >= 0 } {
+        set is_pio false
+      } elseif { ! $is_pio } {
+        lappend qsf_lines $line
+      }
+    }
+    close $qsf_fp
+    set qsf_fp [open $logic_qsf w]
+    puts $qsf_fp "# pio_begin  >>>>>> DO NOT MODIFY THIS SECTION! >>>>>>"
+    puts $qsf_fp "set_instance_assignment -name VIRTUAL_PIN ON -to *"
+    puts $qsf_fp "# pio_end    <<<<<< DO NOT MODIFY THIS SECTION! <<<<<<"
+    foreach line $qsf_lines {
+      puts $qsf_fp $line
+    }
+    close $qsf_fp
+
+    set af_run af_run.tcl
+    set run_fp [open $af_run]
+    set run_lines {}
+    set is_pio false
+    while { [gets $run_fp line] >= 0 } {
+      if { [string first "pio_begin" $line] >= 0 } {
+        set is_pio true
+      } elseif { [string first "pio_end" $line] >= 0 } {
+        set is_pio false
+      } elseif { ! $is_pio } {
+        lappend run_lines $line
+      }
+    }
+    close $run_fp
+    set run_fp [open $af_run w]
+    puts $run_fp "# pio_begin  >>>>>> DO NOT MODIFY THIS SECTION! >>>>>>"
+    puts $run_fp "set FLOW PACK"
+    puts $run_fp "# pio_end    <<<<<< DO NOT MODIFY THIS SECTION! <<<<<<"
+    foreach line $run_lines {
+      puts $run_fp $line
+    }
+    close $run_fp
+  }
+
+  if { true } {
+    set supra_proj ${LOGIC_DESIGN}.proj
+    set proj_fp [open $supra_proj w]
+    puts $proj_fp {[GuiMigrateSetupPage]}
+    puts $proj_fp "design=$LOGIC_DESIGN"
+    puts $proj_fp "device=$LOGIC_DEVICE"
+    puts $proj_fp ""
+    puts $proj_fp {[GuiMigrateRunPage]}
+    puts $proj_fp "fitting=1"
+    puts $proj_fp "fitter=5"
+    puts $proj_fp "effort=2"
+    puts $proj_fp "skew=2"
+    if { $logic_ip } {
+      puts $proj_fp "flow=0"
+    }
+    close $proj_fp
+  }
+}
+> 
+> if { true } {
+  set pre_asf ${LOGIC_DESIGN}.pre.asf
+  set pre_fp [open $pre_asf r];
+  set pre_lines {}
+  set is_pio false
+  while { [gets $pre_fp line] >= 0 } {
+    if { [string first "db_io_name_priority" $line] >= 0 ||
+         [string first "pio_begin" $line] >= 0 } {
+      set is_pio true
+    } elseif { [string first "pio_end" $line] >= 0 } {
+      set is_pio false
+    } elseif { ! $is_pio } {
+      lappend pre_lines $line
+    }
+  }
+  close $pre_fp
+  set pre_fp [open $pre_asf w]
+  foreach line $pre_lines {
+    puts $pre_fp $line
+  }
+  puts $pre_fp "# pio_begin  >>>>>> DO NOT MODIFY THIS SECTION! >>>>>>"
+  if { "$LOGIC_PRE" != "" } {
+    set logic_fp [open $LOGIC_PRE r]; set logic_data [read $logic_fp]; close $logic_fp
+    puts -nonewline $pre_fp $logic_data
+  }
+  if { [info exists BOARD_PLL_CLKIN] } {
+    puts $pre_fp "set BOARD_PLL_CLKIN $BOARD_PLL_CLKIN"
+  }
+  if { [info exists USB0_MODE] } {
+    puts $pre_fp "set USB0_MODE $USB0_MODE"
+  }
+  puts $pre_fp "set db_io_name_priority true"
+  puts $pre_fp "set ip_pll_vco_lowpower true"
+  if { $LOGIC_COMPRESS } {
+    puts $pre_fp "set_global_assignment -name ON_CHIP_BITSTREAM_DECOMPRESSION \"ON\""
+  } else {
+    puts $pre_fp "set_global_assignment -name ON_CHIP_BITSTREAM_DECOMPRESSION \"OFF\""
+  }
+  puts $pre_fp "# pio_end    <<<<<< DO NOT MODIFY THIS SECTION! <<<<<<"
+  close $pre_fp
+}
+> 
+> if { true } {
+  set asf_asf ${LOGIC_DESIGN}.asf
+  set asf_fp [open $asf_asf r];
+  set asf_lines {}
+  set is_pio false
+  while { [gets $asf_fp line] >= 0 } {
+    if { [string first "db_io_name_priority" $line] >= 0 ||
+         [string first "pio_begin" $line] >= 0 } {
+      set is_pio true
+    } elseif { [string first "pio_end" $line] >= 0 } {
+      set is_pio false
+    } elseif { ! $is_pio } {
+      lappend asf_lines $line
+    }
+  }
+  close $asf_fp
+  set asf_fp [open $asf_asf w]
+  foreach line $asf_lines {
+    puts $asf_fp $line
+  }
+  puts $asf_fp "# pio_begin  >>>>>> DO NOT MODIFY THIS SECTION! >>>>>>"
+  if { "$LOGIC_ASF" != "" } {
+    set logic_fp [open $LOGIC_ASF r]; set logic_data [read $logic_fp]; close $logic_fp
+    puts -nonewline $asf_fp $logic_data
+  }
+  puts $asf_fp "# pio_end    <<<<<< DO NOT MODIFY THIS SECTION! <<<<<<"
+  close $asf_fp
+}
+> 
+> if { true } {
+  set post_asf ${LOGIC_DESIGN}.post.asf
+  set post_fp [open $post_asf r];
+  set post_lines {}
+  set is_pio false
+  while { [gets $post_fp line] >= 0 } {
+    if { [string first "pio_begin" $line] >= 0 } {
+      set is_pio true
+    } elseif { [string first "pio_end" $line] >= 0 } {
+      set is_pio false
+    } elseif { ! $is_pio } {
+      lappend post_lines $line
+    }
+  }
+  close $post_fp
+  set post_fp [open $post_asf w]
+  foreach line $post_lines {
+    puts $post_fp $line
+  }
+  puts $post_fp "# pio_begin  >>>>>> DO NOT MODIFY THIS SECTION! >>>>>>"
+  if { "$LOGIC_POST" != "" } {
+    set logic_fp [open $LOGIC_POST r]; set logic_data [read $logic_fp]; close $logic_fp
+    puts -nonewline $post_fp $logic_data
+  }
+  if { $logic_ip } {
+    puts $post_fp "file mkdir $IP_INSTALL_DIR"
+    puts $post_fp "if { ! \[file exists $IP_INSTALL_DIR/${LOGIC_DESIGN}.sdc\] } {"
+    puts $post_fp "  file copy -force ./${LOGIC_DESIGN}_.sdc $IP_INSTALL_DIR/${LOGIC_DESIGN}.sdc"
+    puts $post_fp "}"
+    puts $post_fp "file copy -force ./${LOGIC_DESIGN}_.ve $IP_INSTALL_DIR/${LOGIC_DESIGN}.ve"
+    puts $post_fp "file copy -force ./alta_db/packed.vx $IP_INSTALL_DIR/${LOGIC_DESIGN}.vx"
+  }
+  puts $post_fp "# pio_end    <<<<<< DO NOT MODIFY THIS SECTION! <<<<<<"
+  close $post_fp
+}
+> 
+> exit
+
+Total 0 fatals, 0 errors, 1 warnings, 0 infos.

+ 91 - 0
platformio.ini

@@ -0,0 +1,91 @@
+[setup]
+boards_dir = boards
+board = agrv2k_407
+board_logic.ve = boot.ve
+#board_logic.compress = true
+
+#ips_dir = ../ips
+ip_name = boot_ip
+logic_dir = logic
+; logic_ve = top.ve
+
+framework = agrv_sdk
+program = 0104_boot_mcu_003
+
+src_dir = src
+include_dir = src
+src_filter = "-<*> +<*.c>+<master/user/app/*.c>+<master/user/db/*.c>+<master/user/inc/*.c>+<master/user/lib/*.c>+<master/user/lzma/*.c>+<master/components/atomlib/*.c>+<master/components/ringBuffer/*.c>"
+src_build_flags = -Isrc -Isrc/master/user/app -Isrc/master/user/db -Isrc/master/user/inc -Isrc/master/user/lib -Isrc/master/user/lzma -Isrc/master/components/atomlib -Isrc/master/components/ringBuffer
+
+lwip_imp_dir =
+tinyusb_imp_dir =
+#lwip_param = freertos
+#tinyusb_param =
+
+#board_build.boot_addr = upload
+#board_build.boot_mode = sram
+#board_upload.address = 0x20000000
+#board_upload.logic_address = 0x80020000
+#board_logic.device = AGRV2KL100
+#board_logic.ve = my_board.ve
+board_upload.address = 0x80000000
+
+board_logic.compress = true
+
+board_build.boot_addr = upload
+board_build.boot_mode = flash_sram
+
+logger_if = UART0
+#upload_port = /dev/ttyUSB0
+#monitor_port = /dev/ttyUSB0
+upload_port = COM3
+monitor_port = COM3
+monitor_speed = 57600
+debug_speed = 10000
+
+debug_tool = jlink-openocd
+upload_protocol = jlink-openocd
+
+build_unflags = -O2
+build_flags = -Os
+              -DLOGGER_BAUD_RATE=${setup.monitor_speed}
+              -DAGRV_FP_STACK=0
+              -DDFU_FPGA_CONFIG=\"fpga_boot.inc\"
+
+build_src_flags = -Wno-cast-align
+
+
+
+[setup_rtt]
+logger_if = RTT
+monitor_port = socket://localhost:19021
+
+
+[platformio]
+boards_dir = ${setup.boards_dir}
+src_dir = ${setup.src_dir}
+include_dir = ${setup.include_dir}
+default_envs = dev
+
+[env]
+platform = AgRV
+extends = setup
+
+[env:dev]
+build_type = debug
+
+[env:release]
+build_type = release
+
+[env:rtt]
+build_type = debug
+extends = setup_rtt
+
+[env:serial]
+build_type = release
+upload_protocol = serial
+upload_speed = 460800
+custom_speed = 115200
+
+
+

+ 453 - 0
src/at24cXX.c

@@ -0,0 +1,453 @@
+#include "at24cXX.h"
+#include "uart.h"
+#include "delay.h"
+
+#define PAGE_SIZE	64
+
+//引脚初始化
+void I2C_init(void)
+{
+    SYS_EnableAPBClock(APB_MASK_GPIO2);
+	SYS_DisableNJTRST();
+    GPIO_SetHigh(IIC_SCL_PORT,IIC_SCL_PIN);
+    GPIO_SetHigh(IIC_SDA_PORT,IIC_SDA_PIN);
+
+    GPIO_SetOutput(IIC_WP_PORT,IIC_WP_PIN);
+    GPIO_SetOutput(IIC_SCL_PORT,IIC_SCL_PIN);
+    GPIO_SetOutput(IIC_SDA_PORT,IIC_SDA_PIN);
+
+    //打开写保护
+	IIC_WRITE_PROTECT_ENABLE();
+}
+
+/***********************iic**************************/
+
+//产生IIC起始信号
+void IIC_Start(void)
+{
+	SDA_OUT();
+    IIC_SDA(1);//IIC_SDA = 1;
+    IIC_SCL(1);//IIC_SCL = 1;
+    delay_us(4);
+    IIC_SDA(0);//IIC_SDA = 0;//START:when CLK is high,DATA change form high to low
+    delay_us(4);
+    IIC_SCL(0);//IIC_SCL = 0;
+}
+
+
+//产生IIC停止信号
+void IIC_Stop(void)
+{
+	SDA_OUT();
+    IIC_SDA(0);//IIC_SDA = 0;
+    IIC_SCL(0);//IIC_SCL = 0;
+    delay_us(4);
+    IIC_SCL(1);//IIC_SCL = 1;
+    delay_us(4);
+    IIC_SDA(1);//IIC_SDA = 1;
+    delay_us(4);
+}
+//等待应答信号到来
+//返回值:
+//		1,接收应答失败
+//    0,接收应答成功
+uint8_t IIC_Wait_Ack(void)
+{
+	volatile uint8_t ucErrTime=0;
+    SDA_IN();  // SDA 配置成输入
+    // IIC_SDA(1);//IIC_SDA=1;
+    delay_us(1);
+    IIC_SCL(1);//IIC_SCL=1;
+    delay_us(1);
+    while(READ_SDA)
+    {
+        ucErrTime++;
+        if(ucErrTime>250)
+        {
+        IIC_Stop();
+        return 1;
+        }
+    }
+    IIC_SCL(0);//IIC_SCL=0;
+    return 0;
+  
+}
+//产生ACK应答
+void IIC_Ack(void)
+{
+	IIC_SCL(0);//IIC_SCL = 0;
+    SDA_OUT();
+    IIC_SDA(0);//IIC_SDA = 0;
+    delay_us(4);
+    IIC_SCL(1);//IIC_SCL = 1;
+    delay_us(2);
+    IIC_SCL(0);//IIC_SCL = 0;
+}
+//不产生ACK应答
+void IIC_NAck(void)
+{
+	IIC_SCL(0);//IIC_SCL = 0;
+    SDA_OUT();
+    IIC_SDA(1);//IIC_SDA = 1;
+    delay_us(4);
+    IIC_SCL(1);//IIC_SCL = 1;
+    delay_us(2);
+    IIC_SCL(0);//IIC_SCL = 0;
+}
+//IIC发送一个字节
+//返回从机有无应答
+//1,有应答
+//0,无应答
+void IIC_Send_Byte(uint8_t txd)
+{                    
+	uint8_t t;
+    SDA_OUT();
+	IIC_SCL(0);//IIC_SCL=0;// 电平置低,开始传输数据
+	for(t=0;t<8;t++)
+	{
+		// IIC_SDA=(txd&0x80)>>7;
+		if((txd&0x80)>>7) IIC_SDA(1);
+		else IIC_SDA(0);
+		txd<<=1;
+		delay_us(4);   //
+		IIC_SCL(1);//IIC_SCL=1;
+		delay_us(2);
+		IIC_SCL(0);//IIC_SCL=0;
+        if(t==7)
+            SDA_IN();
+		delay_us(2);
+	}
+}
+//读1个字节,ack=1时,发送ACK,ack=0,发送nACK
+uint8_t IIC_Read_Byte(uint8_t ack)
+{
+	uint8_t i,receive=0;
+    SDA_IN();//SDA设置为输入
+    for(i=0;i<8;i++ )
+    {
+        IIC_SCL(0);//IIC_SCL=0;
+        delay_us(4);
+        IIC_SCL(1);//IIC_SCL=1;
+        receive<<=1;
+        if(READ_SDA)receive++;
+        delay_us(1);
+    }
+    if(!ack)
+        IIC_NAck();//发送nACK
+    else
+        IIC_Ack(); //发送ACK
+    return receive;
+}
+
+
+/***********************以上为IIC驱动**************************/
+
+
+
+
+
+
+
+
+
+
+
+
+/***********************iic**************************/
+//在AT24CXX指定地址读出一个数据
+//ReadAddr:开始读数的地址
+//返回值  :读到的数据
+uint8_t AT24CXX_ReadOneByte(uint32_t ReadAddr)
+{
+	uint8_t temp;
+	uint8_t addrH,addrL;
+
+	addrH=ReadAddr>>8;
+	addrL=ReadAddr&0xff;
+
+	IIC_Start();
+
+	IIC_Send_Byte(0xa0);
+
+	IIC_Wait_Ack();
+	IIC_Send_Byte(addrH);   //发送高地址
+	IIC_Wait_Ack();
+   	IIC_Send_Byte(addrL);   //发送低地址
+	IIC_Wait_Ack();
+	IIC_Start();
+	IIC_Send_Byte(0xa1);         //进入接收模式
+
+	IIC_Wait_Ack();
+	temp=	IIC_Read_Byte(0);
+	IIC_Stop();//产生一个停止条件
+
+	delay_us(4);
+	return temp;
+}
+//在AT24CXX指定地址写入一个数据
+//WriteAddr  :写入数据的目的地址
+//DataToWrite:要写入的数据
+void AT24CXX_WriteOneByte(uint32_t WriteAddr,uint8_t DataToWrite)
+{
+	uint8_t addrH,addrL;
+
+	addrH=WriteAddr>>8;
+	addrL=WriteAddr&0xff;
+
+	IIC_Start();
+
+	IIC_Send_Byte(0xa0);
+
+	IIC_Wait_Ack();
+	IIC_Send_Byte(addrH);   //发送高地址
+	IIC_Wait_Ack();
+	IIC_Send_Byte(addrL);   //发送低地址
+	IIC_Wait_Ack();
+	IIC_Send_Byte(DataToWrite);     //发送字节
+	IIC_Wait_Ack();
+	IIC_Stop();//产生一个停止条件
+  
+	delay_ms(10);//两次写操作,必须加间隔,否则写不进去
+}
+//在AT24CXX里面的指定地址开始读出指定个数的数据
+//ReadAddr :开始读出的地址 对24c02为0~255
+//pBuffer  :数据数组首地址
+//NumToRead:要读出数据的个数
+void AT24CXX_Read(uint32_t ReadAddr,uint8_t *pBuffer,uint16_t NumToRead)
+{
+//	OS_ERR err;
+	uint8_t addrH,addrL;
+	uint16_t lentmp,lentow,lens;
+	uint8_t tmp;
+
+	if(NumToRead==0)
+		return;
+	
+//	I2C_init();
+//	OSTimeDlyHMSM(0, 0, 0, 40, OS_OPT_TIME_DLY, &err);
+//	delay_ms(1);//40
+	// delay_us(500);
+	
+	lentmp=NumToRead;
+	while(lentmp)
+	{
+		tmp=ReadAddr%PAGE_SIZE;
+		tmp=PAGE_SIZE-tmp;
+		if(tmp>=lentmp)//当页剩余空间大于要写入的长度
+		{
+			lentow=lentmp;
+		}
+		else
+		{
+			lentow=tmp;//写入长度只能是剩余空间长度
+		}
+		lentmp=lentmp-lentow;//计算要在下一页写入的长度
+		lens=lentow;
+		addrH=ReadAddr>>8;
+		addrL=ReadAddr&0xff;
+
+		IIC_Start();
+
+		IIC_Send_Byte(0xa0);//写
+		IIC_Wait_Ack();
+
+		IIC_Send_Byte(addrH);   //发送高地址
+		IIC_Wait_Ack();
+	   	IIC_Send_Byte(addrL);   //发送低地址
+		IIC_Wait_Ack();
+
+		delay_us(4);
+		IIC_Start();
+		IIC_Send_Byte(0xa1);  //读       //进入接收模式
+		IIC_Wait_Ack();
+
+		while(lentow)
+		{
+			*pBuffer=IIC_Read_Byte(1);
+			pBuffer++;
+			//ReadAddr++;
+			lentow--;
+			
+		}
+		IIC_Read_Byte(0);
+		IIC_Stop();//产生一个停止条件
+
+		delay_us(4);
+		//printf("at24 read %d %d\r\n", ReadAddr, lens);
+		ReadAddr=ReadAddr+lens;//下一页的地址
+	}
+	//打开写保护
+//	IIC_WRITE_PROTECT_ENABLE();
+}
+//在AT24CXX里面的指定地址开始写入指定个数的数据
+//WriteAddr :开始写入的地址 对24c02为0~255
+//pBuffer   :数据数组首地址
+//NumToWrite:要写入数据的个数
+// 每128bytes为一个page,写操作不能跨页
+void AT24CXX_Write(uint32_t WriteAddr,uint8_t *pBuffer,uint16_t NumToWrite)
+{
+	uint8_t addrH,addrL;
+	uint16_t lentmp,lentow,lens;
+	uint8_t tmp;
+	
+	if(NumToWrite==0)
+		return;
+	
+	//关闭写保护
+	IIC_WRITE_PROTECT_DISABLE();
+//	delay_ms(1);//10
+	delay_us(10);
+
+	lentmp=NumToWrite;
+	while(lentmp)
+	{
+		tmp=WriteAddr%PAGE_SIZE;
+		tmp=PAGE_SIZE-tmp;
+		if(tmp>=lentmp)//当页剩余空间大于要写入的长度
+		{
+			lentow=lentmp;
+		}
+		else
+		{
+			lentow=tmp;//写入长度只能是剩余空间长度
+		}
+		lentmp=lentmp-lentow;//计算要在下一页写入的长度
+		lens=lentow;
+
+		addrH=WriteAddr>>8;
+		addrL=WriteAddr&0xff;
+
+		IIC_Start();
+
+		IIC_Send_Byte(0xa0);
+
+		IIC_Wait_Ack();
+		IIC_Send_Byte(addrH);   //发送高地址
+		IIC_Wait_Ack();
+		IIC_Send_Byte(addrL);   //发送低地址
+		IIC_Wait_Ack();
+
+		while(lentow--)
+		{
+			IIC_Send_Byte(*pBuffer);
+			IIC_Wait_Ack();
+			pBuffer++;
+		}
+		IIC_Stop();//产生一个停止条件
+		// if(lentmp)
+			delay_ms(6);
+		//printf("at24 write %d %d %d, %d\r\n", WriteAddr, lens, addrH, addrL);
+		WriteAddr=WriteAddr+lens;//下一页的地址
+	}
+  
+//	delay_ms(10);//两次写操作,必须加间隔,否则写不进去	,最小5ms
+	//打开写保护
+	IIC_WRITE_PROTECT_ENABLE();
+}
+void AT24CXX_clr(uint32_t WriteAddr,uint32_t NumToWrite)
+{
+	uint8_t addrH,addrL;
+	uint16_t lentmp,lentow,lens;
+	uint8_t tmp;
+	
+	//关闭写保护
+	IIC_WRITE_PROTECT_DISABLE();
+
+	lentmp=NumToWrite;
+	while(lentmp)
+	{
+		tmp=WriteAddr%PAGE_SIZE;
+		tmp=PAGE_SIZE-tmp;
+		if(tmp>=lentmp)
+		{
+			lentow=lentmp;
+		}
+		else
+		{
+			lentow=tmp;
+		}
+		lentmp=lentmp-lentow;
+		lens=lentow;
+
+		addrH=WriteAddr>>8;
+		addrL=WriteAddr&0xff;
+
+		IIC_Start();
+
+		IIC_Send_Byte(0xa0);
+
+		IIC_Wait_Ack();
+		IIC_Send_Byte(addrH);   //发送高地址
+		IIC_Wait_Ack();
+		IIC_Send_Byte(addrL);   //发送低地址
+		IIC_Wait_Ack();
+
+		while(lentow--)
+		{
+			IIC_Send_Byte(0xff);
+			IIC_Wait_Ack();
+		}
+		IIC_Stop();//产生一个停止条件
+		delay_ms(10);
+		WriteAddr=WriteAddr+lens;
+	}
+	//打开写保护
+	IIC_WRITE_PROTECT_ENABLE();
+	delay_ms(10);
+}
+//----------------------EEPROM---------------------------//
+//--------------------------------------------------------EEPROM DATA
+
+/*********************************************END OF FILE**********************/
+#define I2C_DATA_LEN	512
+uint8_t I2c_Buf_Write[I2C_DATA_LEN], I2c_Buf_Read[I2C_DATA_LEN];
+/**
+* @brief I2C(AT24C02)读写测试
+* @param 无
+* @retval 正常返回 1 ,不正常返回 0
+*/
+uint8_t I2C_Test(void)
+{
+	uint16_t i;
+
+	I2C_init();
+
+	EEPROM_INFO("\r\nI2C(AT24C128)字节读写测试\r\n");
+	memset(I2c_Buf_Write, 0, I2C_DATA_LEN);
+	memset(I2c_Buf_Read, 0, I2C_DATA_LEN);
+	// for ( i=0; i< I2C_DATA_LEN; i++ ) //填充缓冲
+	// {
+	// 	I2c_Buf_Write[i] = i+9;
+	// 	AT24CXX_WriteOneByte(i, i);
+	// 	I2c_Buf_Read[i] = AT24CXX_ReadOneByte(i);
+	// }
+	// data_dump("I2C Write", I2c_Buf_Write, I2C_DATA_LEN);
+	// data_dump("I2C Read", I2c_Buf_Read, I2C_DATA_LEN);
+
+	EEPROM_INFO("\r\nI2C(AT24C128)连续地址读写测试\r\n");
+
+	memset(I2c_Buf_Write, 0, I2C_DATA_LEN);
+	memset(I2c_Buf_Read, 0, I2C_DATA_LEN);
+	for ( i=0; i< I2C_DATA_LEN; i++ ) //填充缓冲
+	{
+		I2c_Buf_Write[i] = i+1;
+	}
+	// AT24CXX_clr(512, I2C_DATA_LEN);
+	// delay_ms(10);
+	// AT24CXX_Read(512, I2c_Buf_Read, I2C_DATA_LEN);
+	// data_dump("I2C Read", I2c_Buf_Read, I2C_DATA_LEN);
+	// delay_ms(10);
+	
+	printf("1\n");
+	AT24CXX_Write(512, I2c_Buf_Write, I2C_DATA_LEN);
+	printf("2\n");
+	delay_ms(10);
+	printf("3\n");
+	AT24CXX_Read(512, I2c_Buf_Read, 64);
+	data_dump("I2C Write", I2c_Buf_Write, I2C_DATA_LEN);
+	data_dump("I2C Read", I2c_Buf_Read, I2C_DATA_LEN);
+	
+	EEPROM_INFO("\r\nI2C(AT24C128)读写测试成功\r\n");
+
+	return 1;
+}

+ 45 - 0
src/at24cXX.h

@@ -0,0 +1,45 @@
+#ifndef AT24CXX_H__
+#define AT24CXX_H__
+#include "board.h"
+
+#define IIC_WP_PORT     GPIO2
+#define IIC_WP_PIN		GPIO_BIT0
+
+#define IIC_SDA_PORT    GPIO2
+#define IIC_SDA_PIN		GPIO_BIT2
+
+#define IIC_SCL_PORT	GPIO2
+#define IIC_SCL_PIN     GPIO_BIT1
+
+#define SDA_IN()    GPIO_SetInput(IIC_SDA_PORT,IIC_SDA_PIN)
+#define SDA_OUT()   {GPIO_SetOutput(IIC_SDA_PORT,IIC_SDA_PIN);}
+
+#define IIC_SCL(n)  (n?GPIO_SetHigh(IIC_SCL_PORT,IIC_SCL_PIN) : GPIO_SetLow(IIC_SCL_PORT,IIC_SCL_PIN))
+#define IIC_SDA(n)  (n?GPIO_SetHigh(IIC_SDA_PORT,IIC_SDA_PIN) : GPIO_SetLow(IIC_SDA_PORT,IIC_SDA_PIN))
+
+#define READ_SDA GPIO_GetValue(IIC_SDA_PORT, IIC_SDA_PIN)
+
+//写保护,低电平关闭,可以写入;高电平打开,不能写入
+#define IIC_WRITE_PROTECT_ENABLE()   {GPIO_SetHigh(IIC_WP_PORT, IIC_WP_PIN);}
+#define IIC_WRITE_PROTECT_DISABLE()  {GPIO_SetLow(IIC_WP_PORT, IIC_WP_PIN);}
+
+void I2C_init(void);
+void IIC_Start(void);
+void IIC_Stop(void);
+uint8_t IIC_Wait_Ack(void);
+void IIC_Ack(void);
+void IIC_NAck(void);
+void IIC_Send_Byte(uint8_t txd);
+uint8_t IIC_Read_Byte(uint8_t ack);
+
+uint8_t AT24CXX_ReadOneByte(uint32_t ReadAddr);
+void AT24CXX_WriteOneByte(uint32_t WriteAddr,uint8_t DataToWrite);
+void AT24CXX_Read(uint32_t ReadAddr,uint8_t *pBuffer,uint16_t NumToRead);
+void AT24CXX_Write(uint32_t WriteAddr,uint8_t *pBuffer,uint16_t NumToWrite);
+void AT24CXX_clr(uint32_t WriteAddr,uint32_t NumToWrite);
+
+uint8_t I2C_Test(void);
+
+#define EEPROM_INFO(fmt,arg...)           printf("<<-EEPROM-INFO->> "fmt"\n",##arg)
+
+#endif // !

+ 401 - 0
src/bsp.c

@@ -0,0 +1,401 @@
+/*
+ * @Description: 
+ * @Version: 2.0
+ * @Author: Seven
+ * @Date: 2023-08-29 14:35:07
+ * @LastEditors: Seven
+ * @LastEditTime: 2023-11-16 13:47:33
+ */
+#include "bsp.h"
+#include "hamming.h"
+#include "at24cXX.h"
+#include "update.h"
+#include "myflash.h"
+#include "ota.h"
+
+uint32_t apb_clken;
+uint32_t misc_ctrl;
+
+uint8_t run_led_state = 0;
+uint32_t count = 0;
+uint16_t read_data_dr2 = 0, write_data_dr2 = 0;
+uint8_t updata_flag = 0;
+uint32_t read_crc1,read_crc2,read_crc3;
+uint32_t get_crc1,get_crc2,get_crc3;
+uint32_t datalen1,datalen2,datalen3;
+uint8_t app1_check_result,app2_check_result,app3_check_result;
+uint8_t app1_check_num=0,app2_check_num=0,app3_check_num=0;
+uint8_t jump_flag = 0;
+uint32_t update_addr=0,update_len=0;
+uint16_t read_data_dr=0;
+uint8_t copy_addr=0,update_type;
+
+device_public_info_t device_public_info;
+device_mcu_info_t device_mcu_info;
+// MqttIdPort mqttidport;
+
+uint32_t Reset_cnt = 0;
+uint8_t updata_flag;
+
+void bsp_init(void)
+{
+    SYS_SetHSIConfig(0xf);
+    SYS_SwitchHSIClock();
+
+    // Provide a minimal working FPGA configuration to avoid problems if the default configuration is corrupted.
+ #ifdef DFU_FPGA_CONFIG
+    SYS->APB_CLKENABLE = APB_MASK_FCB0; // Disable all peripherial clocks execpt for FCB to avoid any noise from FPGA
+    __attribute__ ((aligned(4))) uint8_t fpga_config[] = {
+ #include DFU_FPGA_CONFIG
+    };
+    FCB_AutoDecompress((uint32_t)fpga_config);
+#endif
+    SYS_SwitchPLLClock(SYS_HSE_BYPASS_OFF); //use hse
+}
+
+
+//函数功能:设置看门狗复位周期为4秒
+void IWDG_Config(void)
+{
+    uint32_t sleep_ms = (1 << 12) * (1 << (4 + 1)) * RTC_PERIOD / 1000000;
+    // printf("Iwdg with pr %d will trigger every %d ms. Will%s freeeze in stop. Will%s freeeze in standby.\n",
+    //           4, sleep_ms,
+    //           IWDG_FREEZE_STOP & IWDG_STOP_FREEZE    ? "" : " not",
+    //           IWDG_FREEZE_STOP & IWDG_STANDBY_FREEZE ? "" : " not");
+    RTC_Init(board_rtc_source());
+    IWDG_SetPrescaler(0x04);
+    IWDG_SetFreezeMode(IWDG_FREEZE_STOP);
+    IWDG_SetClkSource(IWDG_CLK_SOURCE_LSE);
+    IWDG_Enable();
+}
+
+//喂狗
+void IWDG_feed(void)
+{
+    IWDG_ReloadCounter();
+}
+
+
+//eeprom上电初始化处理
+void eeprom_init_handle(void)
+{
+	AT24CXX_Read(DEVICE_PUBLIC_INFO_ADDR,(uint8_t *)&device_public_info,sizeof(device_public_info_t));
+
+	AT24CXX_Read(DEVICE_VERSION_INFO_ADDR,(uint8_t *)&device_mcu_info,sizeof(device_mcu_info_t));
+	
+	AT24CXX_Read(DEVICE_RESET_ADDR,(uint8_t *)&Reset_cnt,4);
+
+    if(device_public_info.eeprom_first_flag != EEPROM_FIRST_FLAG)//第一次读eeprom
+    {
+        Reset_cnt = 0;
+        device_public_info.eeprom_first_flag = EEPROM_FIRST_FLAG;
+        AT24CXX_Write(DEVICE_PUBLIC_INFO_ADDR,(uint8_t *)&device_public_info.eeprom_first_flag,2);
+    }
+}
+
+//更新eeprom信息
+void eeprom_info_update(void)
+{
+	Reset_cnt++;
+	AT24CXX_Write(DEVICE_RESET_ADDR,(uint8_t *)&Reset_cnt,4);
+	
+	//如果bt版本不对,写bt版本
+	if(device_mcu_info.bootloader_ver != SOFTWARE_VERSION_BOOT)
+	{
+		device_mcu_info.bootloader_ver = SOFTWARE_VERSION_BOOT;
+		AT24CXX_Write(DEVICE_VERSION_INFO_ADDR,(uint8_t *)&device_mcu_info.bootloader_ver,4);
+	}
+		
+	//如果执行过升级或回退,写pt、app1、2、3版本
+	if(updata_flag)
+	{
+		updata_flag = 0;
+//		HM_encode((uint8_t *)&device_mcu_info.app1_ver,code_buf,12);
+		AT24CXX_Write(DEVICE_VERSION_INFO_ADDR+4,(uint8_t *)&device_mcu_info.pt_ver,16);
+	}
+}
+
+
+
+//设置标记高位取反
+//将一个数设置为高八位是低八位的取反
+uint16_t set_flag_not(uint16_t data)
+{
+	uint16_t temp_data,ret_data = 0;
+	uint16_t temp_h,temp_l;
+	temp_data = data;
+	temp_h = ((~temp_data)<<8)&0xff00;
+	temp_l = temp_data&0x00ff;
+	ret_data = temp_h | temp_l;
+	return ret_data;
+}
+
+//标记高位取反判断
+//0 错误,1 正确
+uint8_t flag_not_cmp(uint16_t data)
+{
+	uint8_t ret = 0;
+	uint16_t temp_data;
+	uint8_t temp_h,temp_l;
+	temp_data = data;
+	temp_h = (uint8_t)((temp_data&0xff00)>>8);
+	temp_l = (uint8_t)(temp_data&0x00ff);
+	if((temp_h^temp_l) == 0xff)
+	{
+		ret = 1;
+	}
+	return ret;
+}
+
+//crc32校验
+uint32_t crc_block_data_calculate(uint32_t *buf, uint32_t len)
+{
+    uint32_t i,data;
+    for(i = 0; i < len; i++)
+    {
+        CRC_FeedData32(CRC0, buf[i]);
+    }
+    data = CRC_ReadData32(CRC0);
+    return data;
+}
+
+/*
+对app进行校验
+参数:addr:app首地址
+	 len: app长度
+	 checkdata:计算的crc值
+返回:0:校验正确,1:校验失败
+*/
+uint8_t app_check(uint32_t addr, uint32_t len, uint32_t *checkdata)
+{
+	uint8_t ret = 0;
+	uint32_t datalen,read_crc,get_crc;
+	datalen = Flash_DatalenRead(addr,len);
+	read_crc = *(uint32_t*)(addr + datalen-4); //CRC校验
+
+    //计算crc32
+    SYS_EnableAHBClock(AHB_MASK_CRC0);
+    CRC_Reset(CRC0);
+    get_crc = crc_block_data_calculate((uint32_t *)addr,(datalen -4)/4);
+    SYS_DisableAHBClock(AHB_MASK_CRC0);
+
+    printf("len:<0x%08x,%u>,read_crc:0x%08x,get_crc:0x%08x\n",datalen,datalen,read_crc,get_crc);
+	
+	*checkdata = get_crc;
+	if(read_crc != get_crc)
+	{
+		ret = 1;
+	}
+	return ret;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////
+//升级流程
+void updatee_process(void)
+{
+    read_data_dr2 = RTC_ReadBackupRegister(BKP_DR2);
+    printf("BKP_DR2=%04x\n",read_data_dr2);
+    if(flag_not_cmp(read_data_dr2))
+    {
+        // read_data_dr=RTC_ReadBackupRegister(2);//升级的固件类型
+        // if(read_data_dr == 0x02)//升级产测
+		// {
+		// 	update_addr = OTA_UPDATE_PT_FLASH_START_ADDR;
+		// 	update_len = OTA_UPDATE_PT_FLASH_SIZE;
+		// 	copy_addr = UPDATE_ENUM_PT;
+		// 	update_type = 2;
+		// 	printf("升级产测\n");
+		// }
+		// else if(read_data_dr == 0x03)//升级app
+		// {
+		// 	update_addr = OTA_UPDATE_APP1_FLASH_START_ADDR;
+		// 	update_len = OTA_UPDATE_APP1_FLASH_SIZE;
+		// 	copy_addr = UPDATE_ENUM_APP1;
+		// 	update_type = 3;
+		// 	printf("升级app\n");
+		// }
+        // else if(read_data_dr == 0x03)//升级fpga
+        // {
+        //     update_addr = OTA_UPDATE_FPGA_FLASH_START_ADDR;
+		// 	update_len = OTA_UPDATE_FPGA_FLASH_SIZE;
+		// 	copy_addr = UPDATE_ENUM_FPGA;
+		// 	update_type = 4;
+		// 	printf("升级fpga\n");
+        // }
+
+        update_addr = OTA_UPDATE_APP1_FLASH_START_ADDR;
+        update_len = OTA_UPDATE_APP1_FLASH_SIZE;
+        copy_addr = UPDATE_ENUM_APP1;
+        update_type = 3;
+        printf("升级app\n");
+
+        if((read_data_dr2&0x00ff) == UPDATA_FLAG)//升级
+		{
+			printf("updata begin\n");
+			update_handle();
+			
+		}
+        else if((read_data_dr2&0x00ff) == BACKOFF_FLAG)//回退
+        {
+            printf("back off begin\n");
+            backoff_handle();
+        }
+        else if((read_data_dr2&0x00ff) == BACKOFF_OVER)//回退失败
+		{
+			RTC_WriteBackupRegister(BKP_DR2,0x0000);
+		}
+    }
+}
+
+//升级部分
+void update_handle(void)
+{
+    uint8_t i;
+    //校验app1
+    app1_check_result = app_check(update_addr,update_len,&get_crc1);
+    app3_check_result = app_check(OTA_UPDATE_APP3_FLASH_START_ADDR,OTA_UPDATE_APP3_FLASH_SIZE,&get_crc3);
+
+    for(i = 0; i < 2; i++)
+    {
+        erase_app(UPDATE_ENUM_APP2);
+        IWDG_feed(); 
+    //			printf("erase app2 end\n");
+        copy_app(copy_addr, UPDATE_ENUM_APP2);
+        IWDG_feed(); 
+    //			printf("copy app1 end\n");
+        //校验app2
+        app2_check_result = app_check(OTA_UPDATE_APP2_FLASH_START_ADDR,OTA_UPDATE_APP2_FLASH_SIZE,&get_crc2);
+        if(get_crc1 != get_crc2)//校验错误,拷贝过程出错
+        {
+            printf("copy app1 to app2 error\n");
+        }
+        else{//校验正确
+            break;
+        }
+    }
+    
+    for(i = 0; i < 2; i++)
+    {
+        erase_app(copy_addr);
+        IWDG_feed();
+    //			printf("erase app1 end\n");
+        copy_app(UPDATE_ENUM_APP3, copy_addr);
+        IWDG_feed(); 
+    //			printf("copy app3 end\n");
+        app1_check_result = app_check(update_addr,update_len,&get_crc1);
+        if(get_crc1 != get_crc3)//校验错误,拷贝过程出错
+        {
+            printf("copy app3 to app1 error\n");
+        }
+        else//校验正确
+        {
+            break;
+        }
+    }
+    
+    write_data_dr2 = set_flag_not(BACKOFF_FLAG);
+    RTC_WriteBackupRegister(BKP_DR2,write_data_dr2);
+    
+    if(update_type == 2)//产测
+    {
+        device_mcu_info.app2_ver = device_mcu_info.pt_ver;
+        device_mcu_info.pt_ver = device_mcu_info.app3_ver;
+        updata_flag = 1;
+    }
+    else if(update_type == 3)//app
+    {
+        device_mcu_info.app2_ver = device_mcu_info.app1_ver;
+        device_mcu_info.app1_ver = device_mcu_info.app3_ver;
+        updata_flag = 1;
+    }
+    else if(update_type == 4)//fpga
+    {
+        device_mcu_info.app2_ver = device_mcu_info.fpga_ver;
+        device_mcu_info.fpga_ver = device_mcu_info.app3_ver;
+        updata_flag = 1;
+    }
+}
+
+//回退部分
+void backoff_handle(void)
+{
+    uint8_t i;
+    app2_check_result = app_check(OTA_UPDATE_APP2_FLASH_START_ADDR,OTA_UPDATE_APP2_FLASH_SIZE,&get_crc2);
+
+    for(i = 0; i < 2; i++)
+    {
+        erase_app(copy_addr);
+        IWDG_feed();
+        copy_app(UPDATE_ENUM_APP2, copy_addr);
+        IWDG_feed();
+        app1_check_result = app_check(update_addr,update_len,&get_crc1);
+        if(get_crc1 != get_crc2)//校验错误,拷贝过程出错
+        {
+            printf("copy app2 to app1 error\n");
+        }
+        else//校验正确
+        {
+            break;
+        }
+    }
+    
+    write_data_dr2 = set_flag_not(BACKOFF_OVER);
+    RTC_WriteBackupRegister(BKP_DR2,write_data_dr2);
+    
+    if(update_type == 2)//产测
+    {
+        device_mcu_info.pt_ver = device_mcu_info.app2_ver;
+        updata_flag = 1;
+    }
+    else if(update_type == 3)//app
+    {
+        device_mcu_info.app1_ver = device_mcu_info.app2_ver;
+        updata_flag = 1;
+    }
+    else if(update_type == 4)//fpga
+    {
+        device_mcu_info.fpga_ver = device_mcu_info.app2_ver;
+        updata_flag = 1;
+    }
+}
+
+//跳转
+void run_app(void)
+{
+    UART_DeInit(UARTx(0));
+    SYS_DisableAPBClock(APB_MASK_UARTx(0));
+    SYS->APB_CLKENABLE = apb_clken;
+    SYS->MISC_CNTL = misc_ctrl;
+    SYS_SwitchHSIClock();
+
+    // SYS_EnableAPBClock(APB_MASK_FCB0);
+    // FCB_AutoConfig(DFU_APP_LOGIC_ADDRESS); //restore APP logic
+    // //FCB_AutoDecompress(DFU_APP_LOGIC_ADDRESS);
+    // SYS_DisableAPBClock(APB_MASK_FCB0);
+    
+    run_app1();
+}
+
+
+
+//升级测试
+void update_test(void)
+{
+    uint16_t temp;
+    //置升级标志
+    temp = set_flag_not(UPDATA_FLAG);
+    RTC_WriteBackupRegister(BKP_UPDATE_FLAG, temp);
+    //置升级类型
+    temp = set_flag_not(FIRMTYPE_APP);
+    RTC_WriteBackupRegister(BKP_UPDATE_FIRM_TYPE, temp);
+
+    SYS_SoftwareReset();
+}
+
+//清除升级状态
+void clear_update_status(void)
+{
+    RTC_WriteBackupRegister(BKP_UPDATE_FLAG, 0);
+    RTC_WriteBackupRegister(BKP_UPDATE_STATE, 0);
+}

+ 113 - 0
src/bsp.h

@@ -0,0 +1,113 @@
+/*
+ * @Description:
+ * @Version: 2.0
+ * @Author: Seven
+ * @Date: 2023-09-21 10:16:46
+ * @LastEditors: Seven
+ * @LastEditTime: 2023-11-17 11:22:20
+ */
+#ifndef BSP_H__
+#define BSP_H__
+#include "board.h"
+
+#define DFU_APP_LOGIC_ADDRESS 0x800e7000 //fpga start address
+
+extern uint32_t apb_clken;
+extern uint32_t misc_ctrl;
+
+#define SOFTWARE_VERSION_BOOT  0X01041003
+
+/*
+BKP_DR0:RTC时间是否初始化
+BKP_DR1:升级标志
+BKP_DR2:升级固件类型
+BKP_DR3:升级状态
+*/
+enum BKP_t {
+	BKP_DR0,
+    BKP_DR1,
+    BKP_DR2,
+    BKP_DR3,
+    BKP_DR4,
+    BKP_DR5,
+    BKP_DR6,
+    BKP_DR7,
+};
+#define BKP_UPDATE_FLAG			BKP_DR1		//升级标志
+#define BKP_UPDATE_STATE		BKP_DR2		//升级状态
+#define BKP_UPDATE_FIRM_TYPE	BKP_DR3		//升级固件类型
+
+//升级标记
+#define UPDATA_FLAG  0x81	//升级
+#define BACKOFF_FLAG 0x82	//回退(成功)
+#define BACKOFF_OVER 0x83	//回退完成(升级失败,回退成功)
+#define UPDATE_ERR	 0x84	//升级失败
+
+
+#define DEVICE_PUBLIC_INFO_ADDR     0x00        //公共信息存储地址
+#define DEVICE_VERSION_INFO_ADDR    0x100       //软件版本存储地址
+#define DEVICE_RESET_ADDR			0x140		//复位次数存储
+#define FRAM_MQTT_MSG				0x200		//mqtt信息存储地址
+
+#define EEPROM_FIRST_FLAG   0x5AA5  //是否第一次读eeprom标记
+
+//公共信息
+typedef struct _device_public_info_t
+{
+	uint16_t eeprom_first_flag;					//是否第一次上电
+	uint8_t	eeprom_ver;							//eeprom版本
+	uint8_t config_flag;						//是否配置的标记
+	uint32_t device_sn;            				//设备sn
+	uint16_t device_type;          				//设备类型
+	uint16_t manufactures;         				//产品制造商
+	uint16_t batch_number;         				//批次号
+	uint32_t production_data;      				//出厂日期
+	uint8_t  pcb_ver;              				//PCB版本
+}__attribute__((packed)) device_public_info_t;
+
+//单片机信息
+typedef struct _device_mcu_info_t
+{
+	uint32_t bootloader_ver;					//bootloader版本
+	uint32_t pt_ver;							//产测版本
+	uint32_t app1_ver;							//app1版本
+	uint32_t app2_ver;							//app2版本
+	uint32_t app3_ver;							//app3版本
+    uint32_t fpga_ver;                          //fpga版本
+}__attribute__((packed)) device_mcu_info_t;
+
+// /* mqtt IP地址 端口号*/
+// typedef struct _MQTT_IP_PORT_{
+//     uint8_t flag;                               //是否写入过标记
+//     char port[8];                               //端口号
+//     char ip[32];                                //IP地址
+//     char admin[16];                             //用户名
+//     char password[24];                          //密码
+// }__attribute__((packed)) MqttIdPort;
+
+extern device_public_info_t device_public_info;
+extern device_mcu_info_t device_mcu_info;
+// extern MqttIdPort mqttidport;
+
+extern uint32_t Reset_cnt;
+
+extern uint8_t updata_flag;
+
+void bsp_init(void);
+void IWDG_Config(void);
+void IWDG_feed(void);
+void eeprom_init_handle(void);
+void eeprom_info_update(void);
+uint16_t set_flag_not(uint16_t data);
+uint8_t flag_not_cmp(uint16_t data);
+uint32_t crc_block_data_calculate(uint32_t *buf, uint32_t len);
+void updatee_process(void);
+void update_handle(void);
+void backoff_handle(void);
+void run_app(void);
+uint8_t app_check(uint32_t addr, uint32_t len, uint32_t *checkdata);
+
+
+void update_test(void);
+void clear_update_status(void);
+#endif // !

+ 29 - 0
src/delay.c

@@ -0,0 +1,29 @@
+/*
+ * @Description: 
+ * @Version: 2.0
+ * @Author: Seven
+ * @Date: 2023-08-29 14:43:42
+ * @LastEditors: Seven
+ * @LastEditTime: 2023-08-31 09:16:14
+ */
+#include "delay.h"
+
+void delay_us(uint32_t us)
+{
+    // volatile uint32_t i,j;
+    // for(i = 0; i < us; i++)
+    // {
+    //   for(j = 0; j < 7; j++)
+    //   {
+    //     // ;
+    //   }
+    // }
+    UTIL_IdleUs(us);
+}
+
+void delay_ms(uint32_t ms)
+{
+    // delay_us(ms*1000);
+    UTIL_IdleMs(ms);
+}
+

+ 16 - 0
src/delay.h

@@ -0,0 +1,16 @@
+/*
+ * @Description: 
+ * @Version: 2.0
+ * @Author: Seven
+ * @Date: 2023-08-09 17:46:14
+ * @LastEditors: Seven
+ * @LastEditTime: 2023-08-09 17:47:05
+ */
+#ifndef DELAY_H__
+#define DELAY_H__
+#include "board.h"
+
+void delay_us(uint32_t us);
+void delay_ms(uint32_t ms);
+
+#endif // !

+ 248 - 0
src/fpga_boot.inc

@@ -0,0 +1,248 @@
+0x40,0x20,0x00,0x01,0x00,0x00,0xff,0xff,0x51,0x00,0x00,0x02,0x00,0x00,0x0c,0x82,
+0x20,0x04,0x00,0x80,0x08,0x08,0x4c,0x2e,0x1b,0x0a,0x86,0x43,0xa2,0x51,0x14,0x20,
+0x81,0x42,0x00,0x20,0x04,0x00,0x80,0x18,0xc8,0x42,0x07,0x11,0x88,0x43,0xe1,0x24,
+0x00,0x04,0x6c,0x02,0x08,0x93,0x21,0x00,0x08,0x41,0x08,0x20,0x85,0x2c,0x97,0x4c,
+0x24,0x51,0x48,0x5c,0x4e,0x69,0x38,0x9b,0xce,0xa5,0x30,0x30,0x04,0x08,0x00,0x21,
+0x81,0xbb,0x84,0x02,0x99,0x2c,0x12,0x7b,0x3d,0x00,0xbf,0x9f,0xe7,0xf5,0xfb,0x7d,
+0xde,0xf7,0x7d,0xbf,0x61,0x85,0xc1,0x70,0x7d,0xde,0xf9,0x03,0x29,0x20,0x73,0xf0,
+0x00,0x30,0x5a,0x7f,0x10,0x3f,0xec,0x6f,0xf7,0x85,0x22,0xcf,0x68,0xb4,0xda,0x80,
+0x16,0x4b,0x6d,0xba,0xdf,0x70,0xb8,0xdc,0xae,0x77,0x4b,0xad,0xb6,0xd9,0x64,0xb3,
+0x5a,0xef,0x77,0xcb,0xb5,0xfa,0xff,0x80,0xc0,0xdd,0xed,0xb7,0xab,0xe6,0x1a,0xd1,
+0x82,0xc4,0xe2,0xb1,0x6f,0xfb,0xc5,0x8e,0xcc,0xc0,0x40,0x40,0xc1,0x93,0xc0,0x06,
+0x47,0x27,0x95,0xcb,0xd7,0xb3,0x39,0x2c,0x66,0x7b,0x3f,0x73,0xc7,0x59,0x70,0xfa,
+0x4a,0x46,0x83,0x4f,0xa8,0xc6,0xe1,0x32,0xd9,0x2c,0xdc,0xf7,0x35,0x94,0xd7,0xeb,
+0x76,0x30,0x3c,0xbe,0xa7,0x6f,0x8c,0xd1,0x61,0x74,0xb8,0x7d,0xc6,0xfb,0x05,0xba,
+0xcb,0x4f,0x76,0x9a,0xcc,0xc6,0xcb,0x8d,0xb5,0xce,0xef,0xf9,0x77,0x6e,0x0e,0xf3,
+0x49,0xcc,0xe8,0xe8,0x75,0x7b,0x0c,0xe7,0x23,0x8b,0xae,0xe4,0xe8,0xba,0x5d,0xcb,
+0x1e,0x89,0xe7,0x48,0x18,0x4f,0x40,0x7e,0x1f,0x1f,0x96,0x07,0xe4,0x9e,0xf7,0x7d,
+0x7d,0xeb,0x6f,0x82,0x7b,0xe2,0xf4,0x79,0xe0,0xdf,0x3f,0x4c,0x0f,0xd9,0xeb,0xef,
+0xfd,0x7f,0x7f,0x0f,0x37,0xab,0xf0,0xee,0x3f,0x4f,0xeb,0xe5,0x01,0xbe,0x90,0x2b,
+0xec,0xed,0xc0,0x0d,0xfb,0x9c,0xe7,0xb0,0xd0,0x53,0xa4,0xe0,0xba,0xae,0x3b,0xb2,
+0xec,0x38,0x8d,0xb4,0x1e,0xe6,0x41,0x90,0x6a,0xf7,0x0c,0x43,0x2e,0xa3,0x66,0xeb,
+0x42,0x90,0x93,0xb5,0x0e,0xb9,0x70,0xd4,0x36,0xb5,0x44,0xb0,0x5c,0x3e,0xeb,0xc4,
+0x70,0xab,0xad,0x15,0x37,0xd1,0x3c,0x50,0xc4,0x46,0x2d,0xbc,0x23,0x10,0x42,0x70,
+0xb4,0x73,0x12,0x46,0xcd,0x4c,0x69,0x20,0x37,0x80,0x7c,0x7c,0xb7,0x48,0x32,0x33,
+0x0d,0x21,0xc8,0x8b,0x24,0x8f,0x26,0x2d,0x52,0x4c,0x94,0xc6,0xc9,0xb2,0x92,0x7b,
+0x27,0xc9,0x52,0x9c,0xaf,0x2a,0xc8,0x92,0xbc,0xa7,0x2c,0xc7,0xd2,0xdc,0xa5,0x2e,
+0xc6,0xd2,0xfc,0x9b,0x30,0xc6,0x33,0x1c,0x99,0x32,0xc5,0x53,0x3c,0x8f,0x34,0xc4,
+0xb3,0x5c,0x8d,0x36,0xc3,0xb3,0x7c,0x83,0x38,0xc3,0x13,0x9c,0x81,0x3a,0xc1,0xf3,
+0xbc,0x69,0x3c,0xc1,0x53,0xba,0x0b,0x0d,0xcf,0xb0,0x04,0xf7,0x14,0x50,0x4f,0xc4,
+0xff,0x42,0xca,0x0e,0xf5,0x09,0x06,0xd0,0xcf,0x65,0x11,0x40,0xd1,0x52,0x8d,0x19,
+0x21,0x52,0x54,0x85,0x1b,0x4b,0x52,0x94,0xad,0x15,0x4b,0xb9,0xf4,0x73,0xf3,0x4d,
+0x34,0xb4,0xfb,0xbb,0x4e,0xd3,0x72,0x85,0x43,0x51,0x53,0x33,0x7d,0x01,0x4c,0x53,
+0x95,0x43,0x0f,0x51,0xc0,0x33,0x9d,0x59,0x4f,0x55,0x55,0x7a,0xf7,0x58,0xc2,0x15,
+0x9d,0x13,0x57,0x56,0xf5,0xc5,0x6d,0x5f,0x2d,0x35,0xcb,0xa3,0x60,0xd7,0xf5,0xed,
+0x8a,0xb4,0x58,0x70,0xcd,0x91,0x61,0x58,0x13,0x1d,0x69,0x53,0x4a,0xd6,0x65,0x93,
+0x67,0x4b,0xf6,0x85,0x53,0x63,0xda,0x68,0x1d,0x95,0x13,0x57,0x74,0x8d,0xb3,0x6d,
+0x5b,0x90,0x5d,0xb4,0xa4,0x5c,0x51,0x95,0xc9,0x2a,0x5a,0xb6,0x65,0xcc,0xdc,0x54,
+0xb6,0xc5,0x4f,0x6f,0x55,0xb7,0x85,0xd0,0x00,0x5d,0x91,0xbd,0xe9,0x7a,0xdd,0x56,
+0x45,0xed,0x1f,0xdf,0x17,0xe3,0x51,0x7c,0x5f,0x37,0x05,0xa7,0x7f,0xb4,0xf8,0x0e,
+0x0a,0xd0,0x60,0xf7,0xd5,0x8b,0x84,0x33,0xf8,0x56,0x07,0x75,0xe1,0x76,0x0e,0x1a,
+0xcf,0x61,0xf7,0x9d,0xd1,0x8a,0x37,0x37,0xf6,0x25,0x5f,0x63,0x2c,0x5e,0x2d,0x69,
+0x5e,0x98,0xf3,0x15,0x90,0x4b,0x58,0xde,0x21,0x7d,0xe3,0x95,0xbe,0x46,0xc4,0xe4,
+0xb2,0xf6,0x4f,0x8b,0xdc,0x99,0x63,0x81,0x98,0x64,0x38,0xc6,0x55,0x57,0xe6,0x6c,
+0x0e,0x5d,0x31,0x66,0xb9,0x36,0x45,0x9c,0x55,0x19,0xd3,0x01,0x9e,0x4c,0xd7,0x8d,
+0x6b,0x94,0x61,0x9a,0x0c,0x83,0x6b,0xb4,0x9a,0x1a,0xff,0xa2,0xcd,0x5a,0x3d,0xa3,
+0x9f,0xe6,0xfa,0x4c,0xa5,0xa6,0xd6,0x1a,0x5d,0x35,0xa7,0xaf,0xd7,0x76,0x9d,0xad,
+0xd2,0x9a,0xeb,0x9b,0xa9,0xdd,0xf9,0xb6,0x65,0xb0,0xc5,0x1a,0xcc,0x91,0xb4,0xd0,
+0x9b,0x1a,0xeb,0xaf,0xeb,0x5a,0xbe,0x3b,0xb6,0xc1,0xbb,0x5a,0xf9,0xb7,0xae,0x9a,
+0x8c,0xdd,0xb2,0xec,0x1b,0x9e,0x57,0xba,0xce,0xfb,0xcb,0x43,0x9f,0x65,0xfa,0x06,
+0xff,0x9c,0xf0,0x2d,0xe6,0xef,0x63,0x66,0x37,0x0f,0x14,0xd2,0xf1,0x8b,0x5f,0x06,
+0xb9,0x6f,0x73,0x96,0xfb,0xb9,0x71,0xd8,0x27,0x21,0x35,0xf2,0x8b,0x8f,0x2d,0x3b,
+0x70,0xb9,0xed,0x57,0x5e,0x73,0x52,0xdf,0x25,0x27,0x73,0x93,0x3f,0x3c,0xb8,0x74,
+0x13,0xd7,0x45,0xa3,0x70,0xfd,0x34,0xaf,0xd4,0x59,0xbc,0x44,0x8d,0xda,0xda,0x9d,
+0xbd,0x43,0xd6,0x2d,0xfd,0x74,0xfd,0xd8,0x6a,0x5d,0x96,0xcf,0x67,0xf4,0xbe,0x25,
+0xad,0xe3,0x6a,0xbb,0x47,0x77,0xae,0x75,0x53,0x1f,0x7b,0x22,0xf8,0x3b,0xe7,0x87,
+0xe5,0x71,0xfe,0x66,0xc5,0xe7,0x4b,0xfe,0x82,0xef,0xe9,0x72,0xfe,0xa7,0x0d,0xab,
+0x76,0x7a,0x57,0xaf,0x46,0x7b,0x72,0x5f,0xbb,0xd0,0xfb,0xfd,0x1f,0xc3,0xe3,0xe2,
+0x3f,0x26,0xdd,0xec,0xcb,0x7f,0x35,0x17,0xf5,0x76,0x3f,0x67,0xab,0xe4,0x5b,0xff,
+0x16,0x27,0xf8,0xcb,0x1f,0xea,0x00,0x00,0x81,0x40,0xe0,0x90,0x58,0x34,0x1c,0x00,
+0x0f,0x7f,0xc2,0xe1,0x90,0xd8,0x74,0x3e,0x21,0x11,0x89,0x44,0xdf,0xf0,0x88,0xb4,
+0x5e,0x30,0x20,0x8c,0x45,0xa1,0x51,0x48,0xf4,0x7e,0x41,0x0e,0x8d,0xc8,0xe4,0x92,
+0x58,0x2c,0x76,0x43,0x29,0x95,0x43,0xe4,0xd2,0xd8,0x2c,0x6a,0x5d,0x09,0x95,0xcc,
+0xe6,0x73,0x19,0xb4,0xda,0x51,0x34,0x9d,0x47,0xa6,0xf2,0xd9,0x84,0xba,0x73,0x3b,
+0xa1,0x44,0x27,0xb4,0x59,0x25,0x06,0x87,0x49,0x85,0xd1,0xa4,0x93,0xf9,0x6d,0x22,
+0x95,0x43,0xa6,0x54,0xe1,0x15,0x0a,0x8c,0xee,0xa9,0x19,0x9c,0x55,0xea,0xf5,0x9a,
+0xf4,0x0a,0xad,0x5c,0x9a,0xd7,0xe0,0xf4,0xe9,0x35,0x86,0xc5,0x2a,0xb2,0x56,0x6d,
+0x16,0x99,0x0d,0xae,0x0d,0x66,0x92,0xdb,0x6d,0xd1,0xfb,0x85,0x4e,0xe9,0x75,0x8a,
+0x5d,0xe0,0x97,0x2a,0x3d,0xea,0xb1,0x7c,0xa2,0xde,0x70,0x11,0x1c,0x16,0x0f,0x0b,
+0x34,0xc3,0xcf,0x70,0x98,0x99,0x16,0x2e,0xb7,0x8e,0xb5,0x64,0x26,0x38,0xdc,0x95,
+0x2f,0x0f,0x7e,0x91,0xe5,0xb2,0xf9,0x4c,0xae,0x5e,0x53,0x8b,0xcd,0x46,0xf3,0x99,
+0x2c,0xf5,0x03,0x41,0x6f,0xcc,0xe4,0x75,0x33,0xcd,0x3d,0x9f,0x5b,0x76,0xd7,0xdc,
+0xf6,0x3a,0xed,0x9e,0x6f,0x6b,0x7b,0xdb,0xee,0x37,0x31,0x2d,0x16,0xb3,0x7b,0x2c,
+0xd5,0xe7,0xf8,0x34,0x4d,0xde,0x93,0x8b,0xc6,0xe3,0xc5,0xf4,0xb8,0xee,0x5c,0x63,
+0x9b,0x89,0xe7,0xf3,0x39,0x3c,0x2e,0x9c,0x1f,0xa3,0x85,0xeb,0xd5,0x7a,0xb8,0xfe,
+0xdc,0x9f,0xbb,0x0d,0xef,0xc1,0xbb,0x38,0x0f,0x1f,0x83,0xc3,0x98,0xf3,0xd8,0x3d,
+0x3e,0xaf,0x5f,0x96,0xf5,0xeb,0x81,0xfc,0x2e,0xbf,0x2f,0x67,0xb7,0xed,0x32,0xfc,
+0x7d,0xbe,0x96,0xef,0xcf,0xf5,0x69,0x7f,0xde,0xd4,0x55,0xfc,0x80,0xe0,0x27,0xed,
+0xf2,0x80,0x16,0x28,0x1d,0xe9,0x83,0x1e,0x18,0x39,0xdd,0x84,0x1d,0x58,0x49,0xc9,
+0x85,0x1c,0x58,0x59,0xc1,0x86,0x1b,0xd8,0x69,0xb9,0x87,0x1b,0x58,0x79,0xb1,0x88,
+0x1a,0xd8,0x89,0xa9,0x6f,0xdc,0x48,0x36,0x05,0x82,0x17,0xc6,0x8d,0xd0,0x81,0xa2,
+0x98,0xa1,0x82,0x8b,0x1d,0x48,0xa9,0xe7,0x82,0x95,0xc8,0x99,0xa8,0x8d,0x1e,0x38,
+0xd9,0x5d,0x70,0xe3,0x98,0xc1,0xef,0x8b,0xa3,0x17,0x02,0x11,0x8b,0xe0,0xf8,0xf9,
+0x4f,0x90,0xa4,0x18,0xe9,0x6b,0x8c,0x91,0xc9,0x2a,0x35,0x94,0x17,0x09,0x39,0xdc,
+0x93,0x1d,0xb8,0xf1,0x51,0x8e,0x24,0x99,0x59,0xd7,0x96,0x14,0xa8,0x91,0xa0,0x98,
+0x19,0xd9,0x1a,0x45,0x82,0x65,0x29,0x36,0x44,0x84,0xe6,0x49,0xaa,0x43,0x89,0xe4,
+0x79,0x9a,0x5c,0x57,0xa5,0x47,0x62,0x67,0x95,0xe7,0x59,0x76,0x77,0x74,0xe5,0xe5,
+0x26,0x62,0x69,0xa4,0x86,0xc2,0x71,0x56,0x67,0x37,0x92,0x79,0x73,0xe7,0xb5,0x4a,
+0x6b,0x85,0x68,0x98,0x5e,0x8b,0x86,0x68,0xd8,0x6e,0x8f,0x87,0x69,0x18,0x7e,0x93,
+0x88,0x69,0x58,0x8e,0x97,0x89,0x69,0x99,0x86,0x9b,0x98,0xe7,0x09,0x02,0x51,0xa0,
+0x5c,0xba,0x1d,0x42,0x9f,0x5c,0xea,0x76,0x7e,0xa7,0xe6,0xf9,0x2e,0xa0,0x8e,0xe8,
+0x5a,0x8e,0xaf,0x71,0xea,0x46,0x06,0xaa,0x99,0x6a,0xca,0xae,0xa1,0xab,0x5d,0xfa,
+0xcd,0x3a,0xa9,0x9d,0x2a,0xa2,0xa7,0xad,0x66,0xca,0xde,0xb6,0xae,0x6b,0x8a,0xba,
+0xa2,0xac,0xab,0x15,0x32,0x83,0x7a,0x2b,0xa9,0xda,0xc9,0xb3,0x26,0x9a,0x2a,0xc2,
+0xb5,0x22,0xbb,0x4e,0x8c,0xb5,0x6d,0x9b,0x5e,0x6e,0xb1,0x6c,0x8b,0x3d,0x5f,0xb3,
+0x50,0x4a,0xf1,0x8a,0xb0,0x2b,0xf9,0xb6,0x3f,0xb1,0xeb,0xbb,0x2d,0x46,0xb8,0x9f,
+0x3b,0xb1,0xb3,0xb9,0x16,0x3b,0xa2,0x5b,0xb8,0x27,0xab,0xc1,0x3d,0xbb,0x9f,0x7b,
+0xda,0x86,0xbe,0x13,0x7b,0xe9,0xfa,0xbf,0x2b,0x0b,0x45,0xb7,0xbc,0x92,0xba,0xf9,
+0xda,0xb9,0xb0,0x9b,0x6a,0x8e,0xbd,0x28,0x0c,0x0a,0xca,0xc1,0x14,0x5c,0x03,0x06,
+0x64,0xf0,0xca,0x43,0x0e,0x6d,0x31,0x26,0xbf,0x15,0x68,0x70,0xa7,0x9b,0x1f,0x7c,
+0x72,0x17,0xd6,0x7f,0xc6,0xb1,0x0b,0x4a,0xdd,0xb0,0xec,0x6b,0x7a,0xeb,0xc6,0xda,
+0x7c,0x75,0xaa,0xc5,0xe9,0x2c,0xca,0x94,0xcd,0x29,0x6c,0xda,0x98,0xce,0x29,0xac,
+0xea,0x9c,0xcf,0x29,0xeb,0x13,0x2a,0xb7,0xee,0xab,0x43,0x27,0xc1,0x6f,0xe6,0x7b,
+0x30,0x48,0x30,0x8c,0x83,0x3e,0xaa,0x74,0x0b,0x5b,0x2b,0xd0,0x72,0xdd,0x16,0xf1,
+0xd1,0xd9,0x4d,0x25,0xb2,0xd3,0x6c,0x1d,0x3e,0xdb,0xd4,0x75,0x0d,0x0b,0x2c,0xd1,
+0x34,0x35,0x50,0x08,0x62,0x32,0xe4,0xb4,0x04,0xd9,0xb5,0x4c,0x73,0x56,0x64,0x35,
+0x86,0xdb,0x5c,0xc3,0x77,0x1c,0x62,0xdc,0xba,0x76,0x19,0xe3,0x67,0x4c,0x71,0x4d,
+0xb5,0x8b,0xdb,0xdb,0xac,0x65,0x7f,0xde,0x76,0xed,0xf1,0x26,0xde,0xf8,0x2d,0xf7,
+0x84,0x49,0x78,0x6d,0xaf,0x2f,0xe2,0x54,0xdb,0x63,0x72,0xd7,0xb5,0xd9,0x4f,0x90,
+0xdd,0x39,0x2e,0x47,0x94,0xca,0x75,0xfd,0x4f,0x63,0x9c,0xb9,0x5c,0xcf,0x73,0xe8,
+0x17,0x7e,0x2f,0x9d,0xbf,0x78,0x76,0x1f,0x7e,0x44,0xf4,0xbc,0x8b,0x5a,0xb9,0xfa,
+0x1c,0xd7,0x75,0xbd,0x7a,0x5c,0x0f,0x8c,0x4d,0xba,0x4d,0xde,0xf7,0xe9,0xf8,0xae,
+0x7f,0xb0,0xe5,0xf9,0x6d,0x83,0x52,0xd8,0xbb,0x8e,0x9b,0xb5,0xde,0xbb,0xcc,0xdf,
+0xaf,0xf2,0x3b,0xee,0x8b,0xc0,0xe6,0xfc,0x2f,0x07,0x78,0xf1,0x78,0x3e,0xe9,0x7c,
+0xea,0x5b,0xec,0x8d,0xfe,0xf6,0x20,0x1f,0x6a,0x0b,0xf7,0x23,0x7f,0x7a,0x3d,0xeb,
+0x70,0xbf,0x27,0x39,0xf9,0x33,0xbf,0x9b,0x3d,0xfa,0x33,0xff,0x2f,0xbd,0xf3,0x79,
+0x3e,0x73,0xc3,0xed,0x3b,0x3c,0x47,0xd2,0xe2,0x3d,0x45,0xdf,0xd6,0x61,0x97,0x70,
+0x08,0x40,0x63,0x38,0xe4,0x00,0x01,0x02,0x81,0xc1,0x20,0xb0,0x68,0x3c,0x18,0x1e,
+0xff,0x85,0xc3,0x21,0xb0,0xe8,0x7c,0x42,0x23,0x12,0x89,0xbf,0xe1,0x11,0x68,0xbc,
+0x5c,0x03,0x18,0x8b,0xc2,0xa2,0x91,0xe8,0xfc,0x82,0x1d,0x1b,0x91,0xc9,0x24,0xb0,
+0x58,0xec,0x86,0x53,0x2a,0x87,0xc9,0xa5,0xb2,0xe8,0x44,0xa2,0x57,0x32,0x94,0xcb,
+0xe5,0xd1,0xa9,0xac,0xc6,0x67,0x3a,0x8a,0x4d,0x67,0xb2,0xe9,0xcc,0xee,0x83,0x2c,
+0x9f,0x49,0x26,0xf2,0xfa,0x05,0x0a,0x93,0x15,0xa2,0x53,0x23,0x14,0x8a,0x55,0x06,
+0x9b,0x52,0x98,0x54,0x2a,0xb4,0xba,0x9c,0x18,0x89,0x02,0x10,0x4e,0x2a,0xd5,0x09,
+0x68,0x52,0xb1,0x23,0xa7,0xd7,0xa5,0x76,0x28,0xb5,0x72,0x8f,0x65,0xa4,0xd9,0xec,
+0x56,0x4b,0x5c,0x86,0xdb,0x07,0xb4,0xcf,0xee,0x15,0x1b,0x95,0x4a,0xdf,0x76,0x8f,
+0x5e,0x20,0xb7,0x49,0x6d,0xea,0xf7,0x13,0xbe,0xd3,0x70,0x38,0x28,0x8e,0x12,0x07,
+0x7f,0x93,0x61,0xb0,0xf4,0x3c,0x4c,0xf7,0x1b,0x8e,0x86,0xe1,0x04,0x95,0xba,0xee,
+0x4e,0x69,0x90,0xc8,0xe6,0x73,0x57,0xd2,0x00,0x03,0x17,0x25,0xc9,0x67,0x65,0xa0,
+0x24,0x04,0x98,0x05,0x44,0xd2,0x66,0x73,0x7a,0x29,0x26,0xb3,0x27,0x9b,0xce,0x67,
+0x64,0x1a,0xec,0xc6,0xd6,0xf9,0xb3,0xb5,0x6e,0x77,0x57,0x8b,0x4e,0xbe,0xc7,0xbd,
+0xdf,0x5c,0x80,0x9a,0xbe,0x1c,0xf3,0x77,0x75,0xe4,0x44,0xb9,0x5c,0xbe,0x64,0x43,
+0x9d,0x80,0xe8,0x62,0x3a,0x5a,0x3e,0xa7,0x46,0xfa,0x02,0xd0,0x70,0x63,0x7b,0x1c,
+0x77,0x5b,0xaf,0xd8,0x91,0x64,0x3b,0xb4,0xef,0x1f,0x93,0xc3,0xde,0xf4,0x65,0x3c,
+0xbb,0x8f,0x67,0xab,0x85,0xec,0x85,0xfc,0x7d,0x7f,0x3a,0xbf,0xd6,0xa9,0xf7,0xc4,
+0xe8,0x36,0x9f,0x3c,0x23,0x54,0xd0,0xbd,0xef,0x44,0x00,0xae,0x3c,0xc8,0xe3,0xee,
+0xfc,0x3f,0x28,0x4c,0x13,0x05,0xa2,0xce,0xfb,0x0f,0x07,0x3f,0x4f,0xfc,0x25,0x06,
+0x3f,0x69,0xa8,0x02,0xfe,0xa4,0x70,0x3c,0x1f,0x06,0xc2,0xa9,0x3c,0x3d,0x0f,0xa0,
+0x70,0x83,0x04,0x97,0x43,0x49,0x24,0x4e,0xe7,0xbe,0x0d,0x4b,0x4c,0xe3,0xc2,0xf1,
+0x12,0x05,0x12,0x2f,0x6b,0x03,0x95,0x19,0x2e,0xd1,0x84,0x47,0x10,0xc6,0x11,0xb2,
+0xe1,0x02,0xa7,0xd1,0xe2,0xd6,0xa2,0x0a,0x0c,0x24,0x80,0xb2,0xc7,0x11,0x8c,0x75,
+0x11,0x48,0xaa,0xf4,0x8e,0x00,0x49,0x6a,0xb4,0x9b,0x27,0xaa,0xb2,0x8c,0x93,0x0f,
+0xca,0x4a,0xfc,0x9b,0x2c,0xcb,0x52,0xdc,0xb9,0x2e,0xcb,0xd2,0xfc,0xc1,0x30,0xcc,
+0x53,0x1c,0xc9,0x32,0xa7,0xce,0x32,0x11,0x34,0x23,0x01,0x02,0x8d,0x33,0x24,0xb1,
+0x4a,0x06,0x08,0x23,0x70,0x0c,0xdd,0x3a,0xce,0xd3,0xbb,0xd5,0x0e,0x4f,0x09,0xf0,
+0x51,0x3d,0xbf,0x8c,0xbc,0xfc,0xb6,0xcd,0x54,0x0a,0x5d,0x41,0xcd,0x74,0x22,0x5b,
+0x39,0x51,0x0a,0xc0,0x1e,0xd4,0x24,0x80,0x44,0x05,0x45,0xa3,0x00,0x39,0x14,0x92,
+0xce,0x94,0x92,0xc5,0x3d,0x53,0x14,0xda,0x2c,0x50,0x30,0x94,0xd4,0xbb,0x36,0xa4,
+0xc0,0x95,0x38,0xb9,0xa4,0x80,0x15,0x40,0x82,0x55,0x35,0x2d,0x58,0xb4,0xc4,0xf3,
+0xea,0x0c,0x08,0xa5,0xf5,0x5c,0xbd,0x45,0x24,0x70,0xcd,0x58,0xbf,0x20,0xe0,0x3d,
+0x1c,0xa2,0x57,0x14,0xc5,0x79,0x5c,0xa4,0xad,0x78,0x1e,0x50,0xa5,0xd4,0xba,0x04,
+0xed,0xd2,0x4b,0x08,0x00,0x01,0x56,0xd3,0x7d,0x84,0x81,0x00,0x22,0x15,0x45,0x68,
+0xa4,0xb4,0x35,0xad,0x6c,0xdb,0x4f,0xcd,0x69,0x53,0xbb,0x96,0xdd,0xc1,0x6e,0xa4,
+0xa0,0x0d,0x7b,0x70,0x5b,0x36,0x42,0xa4,0xd0,0x5d,0x13,0xb5,0xca,0x8d,0x80,0x93,
+0x82,0x0d,0x6c,0x4e,0xd7,0x12,0x4b,0x76,0xdc,0xd5,0xcd,0xe9,0x7b,0xac,0x56,0x55,
+0xf4,0x8d,0xdc,0x96,0xb5,0x7e,0xa2,0xde,0x17,0xee,0x09,0x82,0xac,0xe2,0x26,0x07,
+0x7d,0x5f,0x80,0x02,0x6f,0x7c,0xe0,0xd8,0x7e,0x20,0x82,0xd9,0xe9,0xf0,0x0d,0x2f,
+0x56,0x10,0xc2,0x99,0x5e,0xd2,0x13,0x43,0x50,0xd0,0x63,0x68,0x16,0x3a,0x00,0x63,
+0xe0,0x06,0x43,0x91,0xe3,0x40,0x06,0x38,0x00,0x63,0xd9,0x42,0x6b,0x48,0x3a,0xd7,
+0x92,0x2f,0x98,0x3a,0x59,0x92,0x07,0x85,0xaa,0x4d,0x43,0x55,0x93,0x65,0x59,0x16,
+0x59,0x92,0x59,0xb9,0xe6,0x53,0x95,0xe8,0x3a,0x06,0x41,0x9d,0xa0,0x59,0xa4,0x61,
+0x97,0x52,0x58,0x0d,0x7c,0x81,0xd0,0x70,0xd6,0x9f,0xa7,0x20,0x9a,0x86,0x8b,0xaa,
+0x20,0x7a,0xb2,0xb1,0xa4,0x5b,0x20,0x2a,0x11,0x6a,0xe2,0x28,0xb5,0x51,0x83,0x66,
+0xcb,0x6e,0xb1,0xa3,0x67,0xa8,0x16,0xcb,0xb4,0xea,0x5a,0xbe,0xd7,0x4e,0x61,0x34,
+0x26,0xd5,0xa3,0xea,0x7b,0x6e,0xcd,0xa8,0xee,0x5b,0x66,0xef,0xaf,0xcc,0x9b,0x8e,
+0xcf,0xba,0xee,0x7b,0xce,0xfd,0xbc,0x6f,0xbb,0xd7,0x08,0x84,0x01,0x18,0x9a,0xdb,
+0x7b,0x62,0x3a,0xf4,0xc9,0xc3,0xaa,0x7b,0x7d,0xb3,0x8b,0xa0,0xb7,0x5c,0xfd,0xc7,
+0x70,0xb2,0xf6,0xc2,0x92,0xab,0x4b,0x97,0x2c,0x83,0xf2,0x0e,0x50,0x07,0x2d,0x71,
+0x88,0xb8,0x15,0x4c,0x73,0xa9,0xaf,0x3f,0x52,0xeb,0x88,0xde,0x1d,0x30,0x74,0xe9,
+0x1f,0x11,0xaf,0xe9,0x56,0x8f,0x5e,0x83,0xf2,0x98,0x8f,0x14,0x82,0xf3,0x74,0x97,
+0x6a,0x9e,0xb8,0x3d,0xcd,0xb7,0xca,0x74,0x7c,0xbf,0x89,0x6b,0x78,0x18,0x37,0x87,
+0xe2,0xf9,0x5c,0x27,0x67,0x4e,0x06,0x09,0x1d,0x98,0x83,0x75,0xbe,0x5f,0xa9,0x2f,
+0x79,0xeb,0xef,0x63,0x32,0xfa,0xeb,0xc7,0x9b,0x3c,0x7b,0x38,0x87,0xbf,0xea,0xfc,
+0x5f,0x1f,0xc9,0x4e,0x79,0x38,0x37,0x53,0x2d,0xf3,0x2f,0x0e,0xb5,0x82,0x7c,0x35,
+0xcf,0xb7,0xc2,0xfe,0x3e,0x27,0xdf,0x38,0xf8,0xbe,0xef,0xe1,0xb4,0x78,0xbf,0x6d,
+0xc1,0xfc,0x7c,0xa8,0x00,0x02,0x04,0x00,0x01,0x20,0x20,0x70,0x78,0x44,0x26,0x15,
+0x0b,0x86,0x40,0x82,0x30,0xd8,0x50,0x4a,0x21,0x13,0x86,0x02,0x22,0x91,0x78,0xc4,
+0x66,0x35,0x1b,0x8e,0x47,0x63,0xd1,0xf9,0x04,0x86,0x2b,0x22,0x92,0x49,0x64,0xd1,
+0x40,0x24,0x96,0x0b,0x27,0x96,0x48,0x22,0xd2,0xd9,0x84,0xc6,0x65,0x1a,0x11,0x4c,
+0xe6,0xd1,0x00,0x40,0x42,0x6f,0x3b,0x9e,0x43,0x40,0x24,0x08,0x18,0xa2,0x7b,0x43,
+0x8e,0x4e,0x68,0x94,0x7a,0x45,0x26,0x95,0x0d,0xa3,0x52,0xe9,0xd4,0xf8,0x10,0x52,
+0x06,0x18,0xa8,0x49,0xa9,0xb5,0x5a,0xc4,0x88,0xa1,0x4b,0x01,0x08,0x2a,0x15,0x7a,
+0xcd,0x86,0xc5,0x63,0x8a,0xce,0xac,0x90,0x70,0x65,0x9e,0xd5,0x5f,0xb3,0x5a,0xed,
+0xd6,0xfa,0x4d,0x82,0xe1,0x55,0x40,0xdc,0xe9,0x77,0x29,0x6c,0x1a,0xed,0x18,0xba,
+0xcb,0x40,0x37,0xb8,0x9d,0xe3,0x01,0x49,0xbe,0xe0,0xe8,0x78,0x2c,0x35,0x13,0x0b,
+0x89,0x9d,0xe2,0x31,0x93,0xcc,0x5e,0x3e,0x67,0x8e,0xc9,0x4d,0xb2,0x39,0x59,0x86,
+0x53,0x31,0x31,0xcb,0xe6,0xe4,0xf9,0xac,0xf4,0xb3,0x3b,0xa1,0x92,0x68,0x34,0x9a,
+0x7d,0x46,0xa7,0x55,0xab,0xd6,0x6b,0x6c,0x54,0x0d,0x74,0x92,0xff,0xad,0x01,0xec,
+0x64,0x23,0x0d,0xb6,0xe6,0xc5,0xb5,0x8f,0x80,0xb6,0x1a,0xcd,0xc0,0x03,0x79,0xba,
+0x8e,0x70,0x78,0x9c,0x7e,0x47,0x27,0x95,0xcb,0xe6,0x73,0x79,0xdc,0xfe,0x87,0x1f,
+0x87,0xd1,0x84,0xf0,0x7a,0x7d,0x48,0x3f,0x1b,0xb1,0xdb,0x8e,0xf5,0xfb,0x9d,0xae,
+0xe4,0x2a,0xf5,0xe1,0x00,0x4b,0xfc,0x90,0xbf,0x1f,0x87,0xcd,0xe7,0x84,0xfa,0x7b,
+0x9e,0xbf,0x64,0x1f,0xdd,0xdb,0xf8,0x7c,0x60,0x5a,0x3e,0x8e,0x9b,0xb1,0xf8,0xe8,
+0x7e,0xba,0x9f,0x84,0xfd,0xce,0x7f,0x9d,0x17,0xf1,0xcf,0x80,0xdd,0x08,0x16,0x02,
+0x5b,0x5f,0x67,0xdd,0xec,0x81,0xdc,0xf8,0x25,0xcd,0x83,0xdc,0xe8,0x45,0xcc,0x84,
+0xdc,0xd8,0x55,0xcb,0x85,0xdc,0xc8,0x65,0xca,0x86,0xd9,0xe7,0x79,0x14,0x87,0x5c,
+0x98,0x7d,0xca,0x88,0xdc,0x80,0x20,0x60,0x83,0x10,0x78,0x9d,0xc7,0x89,0x5b,0xa4,
+0xa6,0x0d,0x79,0xc0,0x28,0x2e,0x0c,0x8b,0x5c,0x48,0xbd,0xc8,0x8d,0xd8,0x90,0x05,
+0xf3,0x45,0x23,0x98,0xad,0x76,0x8f,0x55,0xc8,0xae,0x35,0x90,0x64,0x79,0x22,0x49,
+0x6a,0xe2,0x17,0x61,0xe0,0x92,0x9e,0x49,0x31,0xd4,0x75,0x9f,0x19,0x3a,0x4f,0x95,
+0xa5,0x79,0x62,0x59,0x96,0xa5,0xb9,0x72,0x5d,0x4b,0x65,0x17,0x46,0x53,0x7b,0x25,
+0x59,0x79,0xcb,0x98,0x1d,0x09,0x91,0xdb,0x57,0x90,0x28,0xf9,0xd4,0x12,0x24,0x99,
+0xb5,0xf9,0x9c,0x20,0xe9,0xcd,0xe7,0x7d,0x5f,0x68,0xed,0xb9,0x90,0x1c,0x49,0xe5,
+0xb9,0x91,0x9f,0x19,0xf5,0xb1,0x9e,0xdb,0xaa,0x05,0xae,0x1a,0x27,0xf7,0xb2,0x85,
+0x6b,0x68,0x36,0xe6,0x8a,0x6b,0x28,0xc6,0xda,0x8e,0x6a,0xe9,0x06,0xc6,0x92,0x6a,
+0x13,0x50,0x01,0x3a,0x10,0x00,0x28,0x30,0x20,0x21,0x11,0xca,0x61,0xb6,0x53,0x69,
+0xc8,0x30,0x88,0x83,0x96,0x6a,0x21,0x09,0x6c,0xdb,0xa6,0xf9,0x08,0x12,0x91,0x70,
+0x59,0x59,0x09,0x14,0x45,0x35,0x5b,0x99,0x62,0x4a,0xa5,0x0c,0xa9,0x1c,0xb1,0x45,
+0x18,0xae,0xe3,0x89,0x26,0x96,0x6a,0x69,0x46,0xba,0x71,0x7f,0x69,0xa8,0xac,0x20,
+0xb1,0x9d,0x08,0x2e,0x6b,0x7d,0xab,0xfa,0xdd,0xf6,0xa8,0x5c,0x70,0x11,0xbf,0xb4,
+0x5e,0xa8,0xae,0x77,0x74,0xa5,0x4b,0x5d,0xce,0x99,0xdc,0xf9,0x89,0x2c,0xb6,0x98,
+0xc9,0xa5,0xa5,0xb7,0x6e,0x7b,0xa2,0xe9,0xba,0xae,0xbb,0xb1,0x4a,0xb4,0xe5,0x0b,
+0x71,0xc2,0xbc,0x51,0x89,0x0e,0xed,0x63,0xed,0xf7,0x39,0xb8,0xb5,0x92,0x7a,0xad,
+0x43,0xbf,0x53,0x0b,0x29,0x17,0x4a,0xef,0x45,0x22,0xd0,0x55,0x90,0x2c,0x19,0xe4,
+0x01,0x2c,0xb4,0x7d,0x0f,0x66,0xee,0x37,0x9f,0x0c,0x47,0x55,0x26,0x7b,0x10,0x42,
+0xf1,0x66,0x1a,0xb9,0x43,0x31,0x27,0x95,0xa7,0x8c,0x63,0xf9,0x26,0xff,0x7d,0x31,
+0xa7,0x72,0xc2,0x6a,0x2c,0x46,0xb0,0x60,0xc9,0x94,0xac,0x0d,0x2d,0xb2,0x29,0xdc,
+0xad,0xa4,0xca,0x1a,0xcc,0x89,0xd8,0xcc,0xda,0xbc,0xd5,0xd4,0xcd,0xda,0xac,0xe5,
+0xf9,0xc9,0x1d,0xbc,0xc5,0xa1,0x51,0x8f,0xfd,0x10,0xff,0x3c,0x00,0x03,0x00,0x80,
+0x45,0x80,0xc0,0x20,0x30,0x28,0x34,0x82,0x01,0x3a,0x4b,0xd5,0xed,0x25,0x02,0xd3,
+0x10,0x3d,0x55,0x21,0xd6,0x75,0x74,0x0b,0x5b,0x79,0x8c,0x02,0x21,0x29,0xd7,0x35,
+0x0d,0x5b,0x5f,0x5e,0xb6,0x3d,0x78,0x00,0x03,0xf4,0x40,0x03,0x45,0xd1,0x90,0x3b,
+0x39,0x5d,0x40,0xd6,0x66,0xe2,0xce,0x56,0x40,0x8c,0xf5,0x1f,0xda,0xcf,0xfd,0xb7,
+0x45,0xd1,0xf5,0x90,0x22,0xce,0xda,0x75,0xdd,0x9f,0x66,0x48,0xb8,0x3d,0x90,0x00,
+0xd8,0xc8,0x34,0x0f,0x68,0xe1,0x75,0x8e,0x3f,0x84,0xd9,0x76,0xad,0xb3,0x6e,0xd1,
+0xd0,0x8c,0xfd,0xae,0xde,0xf7,0xdd,0x13,0x7f,0xe4,0x78,0x90,0x21,0xbf,0xe2,0x35,
+0x94,0x83,0xa3,0xe7,0xf5,0xb4,0x1c,0xc0,0xe3,0x78,0x6e,0x2b,0xac,0xd5,0xf9,0xbe,
+0x59,0x18,0xe6,0x59,0xee,0xc3,0x7e,0xe8,0x3a,0x9d,0x9f,0xb8,0xe4,0xf9,0x2d,0x6b,
+0xa7,0xe7,0xe9,0xfe,0xef,0x89,0xe3,0xbc,0x1d,0xa7,0xb5,0xe7,0x50,0x9a,0xd9,0x73,
+0xde,0x52,0x0f,0x18,0xff,0x3c,0xdd,0x94,0x0d,0xd3,0x71,0xbd,0x2f,0x45,0x24,0xf5,
+0x10,0x2f,0x5e,0xf2,0x40,0xfd,0x3f,0x43,0xd8,0xf7,0x7d,0xa4,0x09,0xc6,0xf3,0x7c,
+0xff,0x6f,0xd5,0xf9,0x7d,0xef,0x9f,0xe0,0x48,0x3d,0x9f,0xb3,0xdf,0xfb,0x7e,0x9f,
+0x67,0xe3,0xfb,0xbf,0x3f,0xc3,0xd6,0xfd,0x3e,0x1f,0x9b,0xf8,0xfa,0x3f,0xaf,0xab,
+0xdc,0xfa,0x50,0x00,0x7b,0xfd,0xfe,0x00,0x81,0xc0,0xde,0x60,0x08,0x48,0x00,0x61,
+0x0a,0x01,0xc2,0xa1,0x70,0xd8,0x7c,0x32,0x13,0x0e,0x87,0xc5,0xa2,0xf1,0x88,0x8c,
+0x2a,0x26,0x00,0x8a,0xc2,0x63,0x91,0xe8,0x84,0x52,0x25,0x1a,0x8f,0xc9,0x64,0x40,
+0x08,0x14,0x12,0x0c,0xff,0x78,0x00,0x18,0x10,0xa0,0x41,0x42,0x14,0xc0,0x40,0x42,
+0x41,0x80,0x89,0xa4,0xd8,0x01,0x38,0x9d,0x46,0x67,0xf1,0x99,0xac,0xde,0x73,0x09,
+0xa1,0x4f,0x28,0x92,0xf9,0xdc,0xf6,0x8b,0x0a,0xa5,0xd2,0x68,0x73,0xea,0x3c,0xa6,
+0x07,0x05,0x83,0x4b,0xa8,0x15,0x8a,0xcd,0x6a,0xb7,0x5c,0xae,0xd7,0x25,0x55,0x58,
+0x1c,0xb9,0x05,0x4d,0xa4,0x59,0x2a,0x14,0x5a,0x55,0x22,0x8d,0x5e,0x8b,0xd1,0xa9,
+0xd6,0xfb,0x5d,0xaa,0xa3,0x70,0xb9,0xda,0x6a,0x16,0x09,0x64,0xb8,0x03,0x19,0xbe,
+0x5b,0x6f,0xf8,0x0c,0x0d,0x7a,0xf3,0x56,0xa7,0x80,0x01,0x04,0x0b,0xa5,0xca,0xd1,
+0x86,0xc1,0x61,0xae,0xb8,0xcb,0x8e,0x2b,0x27,0x77,0xa9,0x61,0x2c,0x51,0x70,0x86,
+0x3b,0x37,0x9c,0xce,0xc2,0x72,0xf2,0xd0,0x04,0xdb,0x35,0x3d,0x10,0x00,0x10,0x37,
+0xe9,0xc5,0xfb,0x25,0x95,0xc7,0x6b,0x31,0xf8,0xba,0x96,0x57,0x21,0xb2,0xd8,0x54,
+0xe5,0x78,0x58,0x75,0x20,0x01,0x89,0x02,0x00,0xa2,0xd3,0xbc,0xf7,0x0b,0x87,0x0a,
+0xd0,0x55,0xf8,0x9c,0x8e,0x4d,0x67,0x8d,0xca,0xe6,0xf3,0xa2,0xd6,0x01,0x50,0x01,
+0xf9,0xbf,0x94,0xa3,0xc1,0xa5,0xb3,0x49,0xfc,

+ 268 - 0
src/hamming.c

@@ -0,0 +1,268 @@
+#include "hamming.h"
+#include "math.h"
+#include <stdbool.h>
+#include <string.h>
+
+//编码
+unsigned char HMBM_74(unsigned char a)
+{
+
+	unsigned char b =0;
+
+	b = a & 0x0F;
+	b = b <<0x03;
+
+	if(b&0x08){b=b^0x03;}
+	if(b&0x10){b=b^0x05;}
+	if(b&0x20){b=b^0x06;}
+	if(b&0x40){b=b^0x07;}
+	
+	return(b & 0x7F);
+
+}
+
+//解码
+unsigned char  HMYM_74(unsigned char  a)
+{
+
+	unsigned char b=0,c=0;
+	b = a;
+	c = 0;
+	if(b&0x40) {c = c^0x07 ;}
+	if(b&0x20) {c = c^0x06 ;}
+	if(b&0x10) {c = c^0x05 ;}
+	if(b&0x08) {c = c^0x03 ;}
+	if(b&0x04) {c = c^0x04 ;}
+	if(b&0x02) {c = c^0x02 ;}
+	if(b&0x01) {c = c^0x01 ;}
+
+	switch(c){
+		case 0 :b = b >> 3 ;break ;
+		case 1 :b = b >> 3 ;break ;
+		case 2 :b = b >> 3 ;break ;
+		case 3 :b = (b^0x08) >> 3 ;break ;
+		case 4 :b = b >> 3 ;break ;
+		case 5 :b = (b^0x10) >> 3 ;break ;
+		case 6 :b = (b^0x20) >> 3 ;break ;
+		case 7 :b = (b^0x40) >> 3 ;break ;
+	}
+
+	return (b & 0x0F);
+}
+
+
+
+//对u32数据编码
+//data:输入的待编码数据
+//code:编码后生成的数据(1字节的原始数据生成2字节的编码数据)
+void HM_encode_u32(uint32_t data, uint32_t *code)
+{
+	int i,j;
+	uint32_t temp = 0;
+	uint8_t data_char[8] = {0};
+	uint8_t data_encode[8] = {0};
+	memset(code,0,2);
+	
+//	原始数据拆分:
+	for(i = 0; i < 8; i++)
+	{
+		data_char[i] = (data>>(4*(7-i))) & 0x0f;
+	}
+	
+	//编码
+	for(i = 0; i < 8; i++)
+	{
+		data_encode[i] = HMBM_74(data_char[i]);
+	}
+	
+	//编码后数据合成
+	for(i = 0; i < 2; i++)
+	{
+		for(j = 0; j < 4; j++)
+		{
+			temp = data_encode[i*4+j];
+			code[i] |= temp<<(3-j)*8;
+		}
+	}
+}
+
+//对u32数据解码
+uint32_t HM_decode_u32(uint32_t *data)
+{
+	int i,j;
+	uint32_t temp = 0;
+	uint32_t data_de=0;
+	uint8_t data_temp[8] = {0};
+	uint8_t data_decode[8] = {0};
+	
+	//	原始数据拆分:
+	for(i = 0; i < 2; i++)
+	{
+		for(j = 0; j < 4; j++)
+		{
+			data_temp[i*4+j] = (data[i]>>(3-j)*8) & 0xff;
+		}
+	}
+	
+	//解码
+	for(i = 0; i < 8; i++)
+	{
+		data_decode[i] = HMYM_74(data_temp[i]);
+	}
+	
+	//解码后数据合成
+	for(i = 0; i < 8; i++)
+	{
+		temp = data_decode[i];
+		data_de |= temp<<4*(7-i);
+	}
+	
+	return data_de;
+}
+
+
+
+//汉明码编码(一个字节)
+void HM_encode_char(uint8_t data, uint8_t *code)
+{
+    int i;
+	uint8_t data_char[2] = {0};
+	memset(code,0,2);
+	
+//	原始数据拆分:
+    data_char[0] = data & 0x0f;
+    data_char[1] = (data>>4) & 0x0f;
+
+	//编码
+	for(i = 0; i < 2; i++)
+	{
+		code[i] = HMBM_74(data_char[i]);
+	}
+}
+
+//汉明码解码(一个字节)
+uint8_t HM_decode_char(uint8_t *code)
+{
+    int i;
+    uint8_t data = 0;
+	uint8_t data_decode[2] = {0};
+	
+	//解码
+	for(i = 0; i < 2; i++)
+	{
+		data_decode[i] = HMYM_74(code[i]);
+	}
+	
+	//解码后数据合成
+    data |= data_decode[0];
+    data |= data_decode[1]<<4;
+
+	return data;
+}
+
+//汉明码编码(多字节)
+//返回编码后的字节数
+void HM_encode(uint8_t *src, uint8_t *des, uint16_t size)
+{
+    int i;
+    memset(des,0,size*2);
+    for(i = 0; i < size; i++)
+    {
+        HM_encode_char(src[i],des+2*i);
+    }
+}
+
+//汉明码解码(多个字节)
+void HM_decode(uint8_t *src, uint8_t *des, uint16_t size)
+{
+    int i;
+    memset(des,0,size/2);
+    for(i = 0; i < size; i=i+2)
+    {
+        des[i/2] = HM_decode_char(src+i);
+    }
+}
+
+
+#define NUM 8
+void hamming_test(uint8_t num) 
+{
+	#if 0
+	int i,j,temp,temp_bit;
+    unsigned char coder_T[NUM] = {0};
+    unsigned char encoder_T[NUM] = {0};
+    unsigned char decoder_T[NUM] = {0};
+
+    srand(TickCounter);
+    printf("汉明码测试:\n");
+    printf("原始数据:");
+
+	//生成原数据
+    for(i = 0; i < NUM; i++)
+    {
+        coder_T[i] = rand()%0x10;
+        printf("%02x ",coder_T[i]);
+    }
+    printf("\n");
+
+	//编码
+	for(i = 0; i < NUM; i++)
+	{
+		encoder_T[i] = HMBM_74(coder_T[i]);
+	}
+	
+    printf("编码数据:");
+    for(i = 0; i < NUM; i++)
+    {
+        printf("%02x ",encoder_T[i]);
+    }
+    printf("\n");
+	
+	printf("共修改%d位\n",num);
+	for(i = 0; i < num; i++)
+	{
+		temp = rand()%(NUM*8);
+		j = temp/8;
+		temp_bit = temp%8;
+		
+		encoder_T[j] ^= 1<<temp_bit;
+		
+		printf("修改第%02d位\n",temp);
+	}
+	printf("修改数据:");
+	for(i = 0; i < NUM; i++)
+    {
+        printf("%02x ",encoder_T[i]);
+    }
+    printf("\n");
+
+	//解码
+	for(i = 0; i < NUM; i++)
+	{
+		decoder_T[i] = HMYM_74(encoder_T[i]);
+	}
+	
+    printf("解码数据:");
+    for(i = 0; i < NUM; i++)
+    {
+        printf("%02x ",decoder_T[i]);
+    }
+    printf("\n");
+	#endif
+	
+	uint32_t data = 0, data_de = 0;
+	uint32_t data_en[2] = {0};
+	
+	srand(0);
+    printf("汉明码测试:\n");
+    
+	data = rand()%0xffffffff;
+	printf("原始数据:%08x\n",data);
+	
+	HM_encode_u32(data,data_en);
+	printf("编码数据:%08x, %08x\n",data_en[0],data_en[1]);
+	
+	data_de = HM_decode_u32(data_en);
+	printf("解码数据:%08x\n",data_de);
+}
+

+ 22 - 0
src/hamming.h

@@ -0,0 +1,22 @@
+/*
+ * @Description: 
+ * @Version: 2.0
+ * @Author: Seven
+ * @Date: 2022-06-19 13:42:39
+ * @LastEditors: Seven
+ * @LastEditTime: 2023-08-31 10:32:43
+ */
+#ifndef HAMMING_H__
+#define HAMMING_H__
+#include "board.h"
+
+void hamming_test(uint8_t num);
+void HM_encode_u32(uint32_t data, uint32_t *code);
+uint32_t HM_decode_u32(uint32_t *data);
+void HM_encode_char(uint8_t data, uint8_t *code);
+uint8_t HM_decode_char(uint8_t *code);
+void HM_encode(uint8_t *src, uint8_t *des, uint16_t size);
+void HM_decode(uint8_t *src, uint8_t *des, uint16_t size);
+
+
+#endif

+ 247 - 0
src/key.c

@@ -0,0 +1,247 @@
+#include "key.h"
+#include "delay.h"
+#include "bsp.h"
+
+key_status_t key_status[KEY_MAX];
+// timeout_t tt_key;
+key_para_t key_para[KEY_MAX];
+void key_init(void)
+{
+    SYS_EnableAPBClock(APB_MASK_GPIO1);
+    // SYS_DisableJTDO();
+    GPIO_SetInput(GPIO1,0x70);
+    key_status_init();
+    // timeout_setValue(&tt_key,10,0xff);
+}
+
+//获取按键电平
+uint8_t get_key_bit(uint8_t key)
+{
+    uint8_t status;
+    switch (key)
+    {
+        case KEY1:
+        status = GET_KEY1();
+        break;
+        case KEY2:
+        status = GET_KEY2();
+        break;
+        case KEY3:
+        status = GET_KEY3();
+        break;
+        default:
+        status = 0;
+        break;
+    }
+    return status;
+}
+
+/*! 
+*  \brief     上电读取按键电平
+*  \param  无
+*/
+void key_status_init(void)
+{
+	int i;
+	for(i = 0; i < KEY_MAX; i++)
+	{
+		key_status[i].last_level = get_key_bit(i);
+	}
+}
+
+/*! 
+*  \brief     实时读取按键电平
+*  \param  无
+*/
+void get_key_bit_realtime(void)
+{
+	int i;
+	uint8_t status;
+	// if(!timeout_isOut(&tt_key))
+	// 	return;
+    delay_ms(10);
+	for(i = 0; i < KEY_MAX; i++)
+	{
+		status = get_key_bit(i);
+		if(status != key_status[i].last_level)
+		{
+			key_status[i].flag = 1;
+			if(status)//高电平 抬起
+			{
+				key_status[i].status = KEY_STATUS_UP;
+			}
+			else
+			{
+				key_status[i].status = KEY_STATUS_DN;
+			}
+			key_status[i].last_level = status;
+		}
+	}
+}
+
+
+/*! 
+*  \brief     按键处理函数
+*  \param  无
+*/
+void key_handle(void)
+{
+    uint8_t i;
+    get_key_bit_realtime();//实时读取按键电平
+    for(i = 0; i < KEY_MAX; i++)
+    {
+        if(key_status[i].flag)
+        {
+            key_status[i].flag = 0;
+            if(key_status[i].status == KEY_STATUS_UP)//抬起
+            {
+                // switch(i)
+                // {
+                //     case KEY1:
+				// 		// printf("key1 up\n");
+                //     break;
+                //     case KEY2:
+                //         // printf("key2 up\n");
+                //         // GPIO_SetHigh(ITSF_PWR_N_PORT,ITSF_PWR_N_BIT);
+
+                //         // YTSF_GPIO_REV4_EN();
+                //         // YTSF_GPIO_REV1_RST();
+                //         // delay_ms(500);
+                //         // YTSF_GPIO_REV1_SET();
+                //     break;
+                //     case KEY3:
+				// 		// printf("key3 up\n");
+                //         // GPIO_SetHigh(ITSF_PWR_P_PORT,ITSF_PWR_N_BIT);
+                //     break;
+                //     default:
+                //     break;
+                // }
+            }
+            else if(key_status[i].status == KEY_STATUS_DN)//按下
+            {
+                // if(key_para[i].flag==0)
+                // {
+                //     key_para[i].flag = 1;
+                //     key_para[i].num = 0;
+                //     timeout_setValue(&key_para[i].tt_key,KEY_TIMEOUT,1);
+                // }
+                // key_para[i].num++;
+                // printf("key%d,key num:%d\n",i+1,key_para[i].num);
+                switch(i)
+                {
+                    case KEY1:
+                        // ytsf_test();
+                        // lora_test();
+                        printf("key1 down\n");
+                        
+                    break;
+                    case KEY2:
+                        // tax_test();
+                        // SPI_FLASH_Test();
+                        // I2C_Test();
+                        printf("key2 down\n");
+                        // GPIO_SetLow(ITSF_PWR_N_PORT,ITSF_PWR_N_BIT);
+                        // YTSF_GPIO_REV4_DN();
+                        // SYS_SoftwareReset();
+
+                        // update_test();//升级测试
+                        // FLASH_Unlock();
+                        // FLASH_EraseSector(0x80020000);
+                        // FLASH_Lock();
+                        
+                        // printf("1\n");
+                    break;
+                    case KEY3:
+						printf("key3 down\n");
+                        // GPIO_SetLow(ITSF_PWR_P_PORT,ITSF_PWR_N_BIT);
+                    break;
+                    default:
+                    break;
+                }
+            }
+        }
+    }
+
+    // key_timeout_handle();
+}
+
+// //按键功能
+// void key_func(uint8_t key, uint8_t num)
+// {
+//     printf("key%d,time%d,num%d\n",key+1,KEY_TIMEOUT,num);
+//     switch(key)
+//     {
+//         case KEY1:
+//             switch(num)
+//             {
+//                 case 1:
+//                     // SPI_FLASH_Test();
+//                     // lora_send_query_firm(device_info.device_sn);//发送
+//                 break;
+//                 case 2:
+//                     // SX126xReset();
+//                     // lora_init();
+//                     // printf("lora reset\n");
+//                 break;
+//                 case 3://离线升级
+//                     // printf("lora index = %d\n",lora_para_choice);
+//                     device_fixed_info.master_updata_start = 1;
+// 			        ota_state.offline_mode = KEY_TRIGGER;
+//                 break;
+//                 case 4:
+//                     // lora_power_init();
+//                     // lora_init();
+//                 break;
+//                 default:
+//                 break;
+//             }
+//         break;
+//         case KEY2:
+//             switch(num)
+//             {
+//                 case 1:
+                    
+//                 break;
+//                 case 2:
+//                 break;
+//                 case 3:
+//                     device_fixed_info.master_updata_start = 1;
+// 			        ota_state.offline_mode = KEY_TRIGGER;
+//                 break;
+//                 default:
+//                 break;
+//             }
+//         break;
+//         case KEY3:
+//             switch(num)
+//             {
+//                 case 1:
+                    
+//                 break;
+//                 case 2:
+//                 break;
+//                 case 3:
+//                 break;
+//                 default:
+//                 break;
+//             }
+//         break;
+//         default:
+//         break;
+//     }
+// }
+
+// //按键超时处理
+// void key_timeout_handle(void)
+// {
+//     uint8_t i;
+//     for(i = 0; i < KEY_MAX; i++)
+//     {
+//         if(timeout_isOut(&key_para[i].tt_key))
+//         {
+//             key_func(i,key_para[i].num);
+//             key_para[i].flag = 0;
+//             key_para[i].num = 0;
+//         }
+//     }
+// }

+ 59 - 0
src/key.h

@@ -0,0 +1,59 @@
+/*
+ * @Description: 
+ * @Version: 2.0
+ * @Author: Seven
+ * @Date: 2023-08-09 15:21:06
+ * @LastEditors: Seven
+ * @LastEditTime: 2023-09-25 10:12:35
+ */
+#ifndef KEY_H__
+#define KEY_H__
+#include "board.h"
+
+//按键编号
+enum {
+    KEY1 = 0x00,
+    KEY2,
+    KEY3,
+    KEY_MAX,
+};
+
+//按键状态
+enum {
+    KEY_STATUS_DN = 0x00,       //按键按下
+    KEY_STATUS_UP = 0x01,       //按键抬起
+    KEY_STATUS_NULL = 0xFF,
+};
+
+#define GET_KEY1()  GPIO_GetValue(GPIO1, GPIO_BIT4)
+#define GET_KEY2()  GPIO_GetValue(GPIO1, GPIO_BIT5)
+#define GET_KEY3()  GPIO_GetValue(GPIO1, GPIO_BIT6)
+
+#define KEY_TIMEOUT (5*1000)    //按键超时时间
+
+//按键信息
+typedef struct _key_status_t
+{
+	uint8_t flag;			//是否需要执行按键功能
+	uint8_t status;			//开关状态
+	uint8_t last_level;		//上次开关电平
+}key_status_t;
+extern key_status_t key_status[KEY_MAX];
+
+//按键功能
+typedef struct _key_para_t
+{
+    uint8_t flag;
+    uint8_t num;
+    // timeout_t tt_key;
+}key_para_t;
+
+
+void key_init(void);
+uint8_t get_key_bit(uint8_t key);
+void key_status_init(void);
+void get_key_bit_realtime(void);
+void key_handle(void);
+void key_timeout_handle(void);
+#endif // 
+

+ 19 - 0
src/led.c

@@ -0,0 +1,19 @@
+/*
+ * @Description: 
+ * @Version: 2.0
+ * @Author: Seven
+ * @Date: 2023-09-21 10:16:46
+ * @LastEditors: Seven
+ * @LastEditTime: 2023-09-21 10:26:22
+ */
+#include "led.h"
+
+void led_init(void)
+{
+    SYS_EnableAPBClock(APB_MASK_GPIO1);
+    GPIO_SetOutput(GPIO1, 0x03);
+    GPIO_SetHigh(GPIO1, GPIO_BIT0);
+    GPIO_SetHigh(GPIO1, GPIO_BIT1);
+    // LED_BM_SB_OFF();
+}
+

+ 15 - 0
src/led.h

@@ -0,0 +1,15 @@
+/*
+ * @Description: 
+ * @Version: 2.0
+ * @Author: Seven
+ * @Date: 2023-08-30 15:20:07
+ * @LastEditors: Seven
+ * @LastEditTime: 2023-08-30 15:23:30
+ */
+#ifndef LED_H__
+#define LED_H__
+#include "board.h"
+
+void led_init(void);
+
+#endif // !

+ 70 - 0
src/main.c

@@ -0,0 +1,70 @@
+/*
+ * @Description: 
+ * @Version: 2.0
+ * @Author: Seven
+ * @Date: 2023-08-30 09:45:29
+ * @LastEditors: Seven
+ * @LastEditTime: 2023-11-17 11:08:17
+ */
+#include "board.h"
+#include "myflash.h"
+#include "update.h"
+#include "delay.h"
+#include "bsp.h"
+#include "led.h"
+#include "at24cXX.h"
+#include "uart.h"
+#include "ota.h"
+#include "key.h"
+
+
+
+
+uint32_t Count = 0;
+int main(void)
+{
+    apb_clken = SYS->APB_CLKENABLE;
+    misc_ctrl = SYS->MISC_CNTL;
+
+    bsp_init();
+    led_init();
+    uart0_init();
+    I2C_init();
+    // I2C_Test();
+    IWDG_Config();
+    printf("boot begin\n");
+    eeprom_init_handle();
+
+    myiap_task();//升级流程处理
+
+    eeprom_info_update();
+	//打印信息
+	printf("bootloader信息:\n");
+	printf(" first init       = %04x\n",device_public_info.eeprom_first_flag);
+	printf(" eeprom ver       = %02x\n",device_public_info.eeprom_ver);
+	printf(" reset num        = %u\n",Reset_cnt);
+	printf(" boot ver         = %08x\n",device_mcu_info.bootloader_ver);
+    printf(" pt ver           = %08x\n",device_mcu_info.pt_ver);
+	printf(" app1 ver         = %08x\n",device_mcu_info.app1_ver);
+	printf(" app2 ver         = %08x\n",device_mcu_info.app2_ver);
+	printf(" app3 ver         = %08x\n",device_mcu_info.app3_ver);
+    printf(" fpga ver         = %08x\n",device_mcu_info.fpga_ver);
+
+    run_app();
+
+    while(1)
+    {
+        delay_ms(500);
+        GPIO_Toggle(GPIO1, 0x01);
+        IWDG_feed();
+        Count++;
+        if(Count > 50)
+        {
+            Count = 0;
+            SYS_SoftwareReset();
+        }
+    }
+}
+
+
+

+ 488 - 0
src/master/components/atomlib/ustdio.c

@@ -0,0 +1,488 @@
+/**
+  ******************************************************************************
+  * @file           ustdio.c
+  * @author         古么宁
+  * @brief          非标准化打印输出
+  ******************************************************************************
+  *
+  * COPYRIGHT(c) 2018 GoodMorning
+  *
+  ******************************************************************************
+  */
+/* Includes ---------------------------------------------------*/
+#include <string.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <ctype.h>  // for isdigit
+#include "usr_cfg.h"
+#include "ustdio.h"
+
+#if CONFIG_SHELL_ENABLE
+/* Private types ------------------------------------------------------------*/
+
+/* Private macro ------------------------------------------------------------*/
+
+#define ZEROPAD 1		/* pad with zero */
+#define SIGN    2		/* unsigned/signed long */
+#define PLUS    4		/* show plus */
+#define SPACE   8		/* space if plus */
+#define LEFT    16		/* left justified */
+#define SMALL   32		/* Must be 32 == 0x20 */
+#define SPECIAL	64		/* 0x */
+
+/* Private variables ------------------------------------------------------------*/
+
+/* Public variables ------------------------------------------------------------*/
+
+fmt_puts_t current_puts = NULL;
+fmt_puts_t default_puts = NULL;
+
+
+const char none        []= "\033[0m";  
+const char black       []= "\033[0;30m";  
+const char dark_gray   []= "\033[1;30m";  
+const char blue        []= "\033[0;34m";  
+const char light_blue  []= "\033[1;34m";  
+const char green       []= "\033[0;32m";  
+const char light_green []= "\033[1;32m";  
+const char cyan        []= "\033[0;36m";  
+const char light_cyan  []= "\033[1;36m";  
+const char red         []= "\033[0;31m";  
+const char light_red   []= "\033[1;31m";  
+const char purple      []= "\033[0;35m";  
+const char light_purple[]= "\033[1;35m";  
+const char brown       []= "\033[0;33m";  
+const char yellow      []= "\033[1;33m";  
+const char light_gray  []= "\033[0;37m";  
+const char white       []= "\033[1;37m"; 
+
+char * default_color = (char *)none;
+
+
+/* Gorgeous Split-line -----------------------------------------------*/
+
+
+/**
+  * @author   古么宁
+  * @brief    重定义 printf 函数。本身来说 printf 方法是比较慢的,
+  *           因为 printf 要做更多的格式判断,输出的格式更多一些。
+  *           所以为了效率,在后面写了 printk 函数。
+  * @return   NULL
+*/
+#ifdef __GNUC__ //for TrueStudio ,Makefile
+
+/*
+#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
+PUTCHAR_PROTOTYPE
+{
+	char  cChar = (char)ch;
+	if (current_puts)
+		current_puts(&cChar,1);
+	return ch;
+}
+*/
+//C/C++ build->Settings->Tool Settings->C Linker->Miscellaneous->Other options 选项空中填写:-u_printf_float
+
+int _write(int file, char *ptr, int len)
+{
+	if (current_puts)
+		current_puts(ptr,len);
+	return len;
+}
+
+
+#else // for keil5
+
+
+#pragma import(__use_no_semihosting)
+//标准库需要的支持函数                 
+struct __FILE 
+{ 
+	int handle; 
+}; 
+
+FILE __stdout;
+//定义_sys_exit()以避免使用半主机模式    
+void _sys_exit(int x) 
+{ 
+	x = x; 
+}
+
+//重定义fputc函数 
+int fputc(int ch, FILE *f)
+{
+	char  cChar = (char)ch;
+	if (current_puts)
+		current_puts(&cChar,1);
+	return ch;
+}
+
+
+#endif 
+
+
+
+/**
+	* @author   这个不是我写的,基本是 linus 写的,我删改了部分代码
+	* @brief    整型数据转符串
+	* @param    str       字符串输出内存
+	* @param    num       需要转换的值
+	* @param    base      转换进制,一般为 8 ,10 , 16
+	* @param    size      输出大小缓冲区
+	* @param    precision 精度
+	* @param    type      格式化,如左右对齐,左边是否填充 0
+	* @return   转换所得字符串长度
+*/	
+static char *number(char *str, long num,int base, int size, int precision,
+                    int type)
+{
+	/* we are called with base 8, 10 or 16, only, thus don't need "G..." */
+	static const char digits[16] = "0123456789ABCDEF"; /* "GHIJKLMNOPQRSTUVWXYZ"; */
+	unsigned long unum ;
+	char tmp[66];
+	char sign, locase,padding;
+	int chgsize;
+
+	/* locase = 0 or 0x20. ORing digits or letters with 'locase'
+	 * produces same digits or (maybe lowercased) letters */
+	locase = (type & SMALL);
+	if (type & LEFT)
+		type &= ~ZEROPAD;  
+
+	padding = (type & ZEROPAD) ? '0' : ' ';
+	sign = 0;
+	if (type & SIGN) {
+		if (num < 0) {
+			sign = '-';
+			num = -num;
+			size--;
+		} 
+		else 
+		if (type & PLUS) {
+			sign = '+';
+			size--;
+		} 
+		else 
+		if (type & SPACE) {
+			sign = ' ';
+			size--;
+		}
+	}
+
+	if (type & SPECIAL) {
+		if (base == 16)
+			size -= 2;
+		else
+		if (base == 8)
+			size--;
+	}
+
+	chgsize = 0;
+	unum = (unsigned)num;
+	do {
+		tmp[chgsize] = (digits[unum % base] | locase) ;
+		++chgsize;
+		unum /= base;
+	}while(unum);
+
+	if (precision < chgsize)
+		precision = chgsize;
+
+	size -= precision;
+	if (!(type & (ZEROPAD + LEFT))){
+		for ( ; size > 0 ; --size )
+			*str++ = ' ';
+	}
+	
+	if (sign)
+		*str++ = sign;
+	
+	if (type & SPECIAL) {
+		if (base == 8)
+			*str++ = '0';
+		else 
+		if (base == 16) {
+			*str++ = '0';
+			*str++ = ('X' | locase);
+		}
+	}
+
+	if (!(type & LEFT)){
+		for ( ; size > 0 ; --size)
+			*str++ = padding ;
+	}
+
+	for ( ; chgsize < precision ; --precision ) 
+		*str++ = '0';
+
+	for ( ; chgsize > 0 ; *str++ = tmp[--chgsize]);
+
+	for ( ; size > 0 ; --size)
+		*str++ = ' ' ;
+
+	return str;
+}
+
+
+
+/**
+	* @author   古么宁
+	* @brief    float 型数据转符串
+	* @param    str       字符串输出内存
+	* @param    num       需要转换的值
+	* @param    size      输出大小缓冲区
+	* @param    precision 精度
+	* @param    type      格式化,如左右对齐,左边是否填充 0
+	* @return   转换所得字符串长度
+*/	
+static char * float2string(char *str,float num, int size, int precision,int type)
+{
+	char tmp[66];
+	char sign,padding;
+	int chgsize;
+	unsigned int ipart ;
+
+	if (type & LEFT)
+		type &= ~ZEROPAD;
+
+	padding = (type & ZEROPAD) ? '0' : ' ';
+
+	if (precision < 0 || precision > 6) // 精度,此处精度限制为最多 6 位小数
+		precision = 6;
+
+	if (num < 0.0f) {  // 如果是负数,则先转换为正数,并占用一个字节存放负号
+		sign = '-';
+		num  = -num ;
+		size--;
+	}
+	else 
+		sign = 0;
+
+	chgsize = 0;
+	ipart = (unsigned int)num; // 整数部分
+
+	if (precision) {           // 如果有小数转换,则提取小数部分
+		static const float mulf[7] = {
+			1.0f,10.0f,100.0f,1000.0f,10000.0f,100000.0f,1000000.0f};
+		unsigned int fpart = (unsigned int)((num - (float)ipart) * mulf[precision]) ;
+		
+		for(int i = 0 ; i < precision ; ++i) { 
+			tmp[chgsize++] = (char)(fpart % 10 + '0');
+			fpart /= 10;
+		}
+		tmp[chgsize++] = '.';
+	}
+
+	do {
+		tmp[chgsize++] = (char)(ipart % 10 + '0');
+		ipart /= 10;
+	}while(ipart);
+
+	size -= chgsize;                 // 剩余需要填充的大小
+
+	if (!(type & LEFT)){             // 右对齐
+		if ('0' == padding && sign) {// 如果是填充 0 且为负数,先放置负号
+			*str++ = sign;
+			sign = 0;
+		}
+		for ( ; size > 0 ; --size)   // 填充 0 
+			*str++ = padding ;
+	}
+
+	if (sign)
+		*str++ = sign;
+
+	for ( ; chgsize > 0 ; *str++ = tmp[--chgsize]);
+
+	for ( ; size > 0 ; --size)   // 左对齐时,填充右边的空格
+		*str++ = ' ' ;
+
+	return str;
+}
+
+
+/**
+  * @author   古么宁
+  * @brief    printk
+  *           格式化输出,类似于 sprintf 和 printf
+  *           用标准库的 sprintf 和 printf 的方法太慢了,所以自己写了一个,重点要快。
+  *           此函数没有输出缓冲区,所以在设计的时候遇到字符 % 会向硬件输出一次,交由
+  *           硬件的输出缓存。
+  * @param    fmt     要格式化的信息字符串指针
+  * @param    ...     不定参
+  * @return   void
+*/
+void printk(const char* fmt, ...) 
+{
+	if (!current_puts) // 无硬件输出,返回
+		return ;
+
+	char tmp[88] ;      // 此段内存仅用于缓存数字转换成的字符串
+	char * substr;
+	unsigned long num;
+	int len , base;
+	int flags;          /* flags to number() */
+	int field_width;    /* width of output field */
+	int precision;      /* min. # of digits for integers; max
+                           number of chars for from string */
+	int qualifier;      /* 'h', 'l', or 'L' for integer fields */
+
+	char * fmthead = (char *)fmt;
+	char * fmtout = fmthead;
+
+	va_list args;
+	va_start(args, fmt);
+
+	for ( ; *fmtout; ++fmtout) {
+		if (*fmtout == '%') {
+			char * str = tmp ;
+
+			if (fmthead != fmtout)   { //先把 % 前面的部分输出
+				current_puts(fmthead,fmtout - fmthead);
+				fmthead = fmtout;
+			}
+
+			/* process flags */
+			flags = 0;
+			base  = 0;
+			do {
+				++fmtout; /* this also skips first '%' */
+				switch (*fmtout) {
+					case '-': flags |= LEFT;    break;
+					case '+': flags |= PLUS;    break;
+					case ' ': flags |= SPACE;   break;
+					case '#': flags |= SPECIAL; break;
+					case '0': flags |= ZEROPAD; break;
+					default : base = 1;
+				}
+			}while(!base);
+
+			/* get field width */
+			if (isdigit(*fmtout)) {
+				field_width = 0 ;
+				do {
+					field_width = field_width * 10 + *fmtout - '0';
+					++fmtout;
+				}while(isdigit(*fmtout));
+				if (field_width > sizeof(tmp))
+					field_width = sizeof(tmp);
+			}
+			else 
+				field_width = -1;
+
+			/* get the precision */
+			if (*fmtout == '.') {
+				precision = 0;
+				for (++fmtout ; isdigit(*fmtout) ; ++fmtout) 
+					precision = precision * 10 + *fmtout - '0';
+				if (precision > sizeof(tmp))
+					precision = sizeof(tmp);
+			}
+			else
+				precision = -1;
+
+			/* get the conversion qualifier *fmt == 'h' ||  || *fmt == 'L'*/
+			if (*fmtout == 'l') {
+				qualifier = *fmtout;
+				++fmtout;
+			}
+			else 
+				qualifier = -1;
+
+			/* default base */
+			base = 10;
+
+			switch (*fmtout) {
+				case 'c':
+					if (!(flags & LEFT))
+						for ( ; --field_width > 0 ; *str++ = ' '); // 右对齐,补全左边的空格
+					*str++ = (char)va_arg(args, int);
+					for ( ; --field_width > 0 ; *str++ = ' ') ;    // 左对齐,补全右边的空格
+					current_puts(tmp,str-tmp);
+					fmthead = fmtout + 1;
+					continue;
+
+				case 's':
+					substr = va_arg(args, char *); 
+					if (!substr)
+						substr = "(NULL)";
+					str = substr ;
+					if (precision > 0)
+						while(*str++ && --precision);
+					else 
+						while(*str++);
+					len = str - substr;          // 其实就是为了实现 strnlen ,此处不希望再进行函数压栈
+					str = tmp;
+					if ((!(flags & LEFT)) && (len < field_width)){  // 右对齐且需要补全空格
+						do{*str++ = ' ';}while(len < --field_width);// 填充空格串
+						current_puts(tmp,str-tmp);
+					} 
+					current_puts(substr,len);                       // 输出子字符串
+					if (len < field_width) {                        // 左对齐且需要补全右边空格
+						do{*str++ = ' ';}while(len < --field_width);
+						current_puts(tmp,str-tmp);
+					}
+					fmthead = fmtout + 1;
+					continue;
+
+				case 'p':
+					if (field_width == -1) {
+						field_width = 2 * sizeof(void *);
+						flags |= ZEROPAD;
+					}
+					str = number(tmp,
+						(unsigned long)va_arg(args, void *), 16,
+						field_width, precision, flags);
+					current_puts(tmp,str-tmp);
+					fmthead = fmtout + 1;
+					continue;
+
+				case 'f':
+					str = float2string(tmp,va_arg(args, double),field_width, precision, flags);
+					current_puts(tmp,str-tmp);
+					fmthead = fmtout + 1;
+					continue;
+
+				/* case '%':
+					*str++ = '%';
+					continue;*/
+
+				/* integer number formats - set up the flags and "break" */
+				case 'o':
+					base = 8;
+					break;
+
+				case 'x':
+					flags |= SMALL;
+				case 'X':
+					base = 16;
+					break;
+
+				case 'd':
+				case 'i':
+					flags |= SIGN;
+				case 'u':
+					break;
+
+				default: 
+					continue;
+			}// switch()
+
+			if (qualifier == 'l')
+				num = va_arg(args, unsigned long);
+			else 
+				num = va_arg(args, int);
+
+			str = number(tmp, num, base, field_width, precision, flags);
+			current_puts(tmp,str-tmp);
+			fmthead = fmtout + 1;
+		}//if (*fmtout == '%')
+	}
+			
+	if (fmthead != fmtout)
+		current_puts(fmthead,fmtout - fmthead);
+		
+	va_end(args);
+}
+#endif

+ 91 - 0
src/master/components/atomlib/ustdio.h

@@ -0,0 +1,91 @@
+/**
+  ******************************************************************************
+  * @file           ustdio.h
+  * @author         古么宁
+  * @brief          非标准化打印输出头文件
+  ******************************************************************************
+  *
+  * COPYRIGHT(c) 2018 GoodMorning
+  *
+  ******************************************************************************
+*/
+
+#ifndef _unstandard_format_
+#define _unstandard_format_
+
+/* Public macro ------------------------------------------------------------*/
+
+#define printl(ptr,len)  do{if (current_puts) current_puts(ptr,len);}while(0)
+
+#define color_printk(color,...) \
+	do{\
+		printk((char *)color);\
+		printk(__VA_ARGS__);  \
+		printk(default_color);\
+	}while(0)
+
+#define Warnings(...) \
+	do{\
+		printk("%sWarning:",(char *)red);\
+		printk(__VA_ARGS__);  \
+		printk(default_color);\
+	}while(0)
+	
+	
+#define Errors(...)   \
+	do{\
+		printk("%sERROR:",(char *)light_red);\
+		printk(__VA_ARGS__);  \
+		printk(default_color);\
+	}while(0)
+
+		
+#define Debug_Here() printk("%sHere is %s()-%d\r\n%s",(char *)green,__FUNCTION__,__LINE__,default_color)
+
+#define Error_Here() printk("%sError on %s()-%d\r\n%s",(char *)light_red,__FUNCTION__,__LINE__,default_color)
+
+
+/* Public types ------------------------------------------------------------*/
+
+typedef void (*fmt_puts_t)(const char * strbuf,unsigned short len);//
+
+/* Public variables ---------------------------------------------------------*/
+
+extern  fmt_puts_t current_puts;
+extern  fmt_puts_t default_puts;
+
+extern const  char	none        [];  
+extern const  char	black       [];  
+extern const  char	dark_gray   [];  
+extern const  char	blue        [];  
+extern const  char	light_blue  [];  
+extern const  char	green       [];  
+extern const  char	light_green [];  
+extern const  char	cyan        [];  
+extern const  char	light_cyan  [];  
+extern const  char	red         [];  
+extern const  char	light_red   [];  
+extern const  char	purple      [];  
+extern const  char	light_purple[];  
+extern const  char	brown       [];  
+extern const  char	yellow      [];  
+extern const  char	light_gray  [];  
+extern const  char	white       []; 
+extern char  * default_color;
+
+
+
+
+/* Public function prototypes -----------------------------------------------*/
+#include "usr_cfg.h"
+
+#if CONFIG_SHELL_ENABLE
+void    printk(const char* fmt, ...);
+#else
+#define printk(fmt_puts_t, ...)
+#endif
+
+int sprintk(char * buffer ,const char * fmt , ...);
+
+#endif
+

+ 169 - 0
src/master/components/ringBuffer/ringBuffer.c

@@ -0,0 +1,169 @@
+#include "board.h"
+#include "type.h"
+#include "ringBuffer.h"
+
+/**********************************************************************************
+** 函数名称:ring_buffer_init()
+** 函数功能:初始化
+** 函数参数:无
+** 创建时间:2009-4-23
+** 第一次修改时间:无
+***********************************************************************************/
+void ring_buffer_init(ring_buffer *ring, uint8 *buff, uint16 size)
+{
+    ring->buffer = buff;
+    ring->buffer_size = size;
+    ring->read_index = 0;
+    ring->save_index = 0;
+}
+
+/**********************************************************************************
+** 函数名称:ring_buffer_save
+** 函数功能:保存一个字节
+** 函数参数:无
+** 创建时间:2009-4-23
+** 第一次修改时间:无
+***********************************************************************************/
+void ring_buffer_save(ring_buffer *ring, uint8 dat)
+{
+    /* save character */
+    ring->buffer[ring->save_index] = dat;
+    ring->save_index++;
+    
+    if(ring->save_index >= ring->buffer_size)
+        ring->save_index = 0;
+
+    /* if the next position is read index, discard this 'read char' */
+    if (ring->save_index == ring->read_index)
+    {
+        ring->read_index ++;
+        if(ring->read_index >= ring->buffer_size)
+            ring->read_index = 0;
+    }
+}
+
+/**********************************************************************************
+** 函数名称:ring_buffer_read
+** 函数功能:读取数据
+** 函数参数:无
+** 创建时间:2009-4-23
+** 第一次修改时间:无
+***********************************************************************************/
+int ring_buffer_read(ring_buffer *ring, uint8 *buffer, uint16 size)
+{
+    uint8 *ptr;
+    
+    ptr = buffer;
+    while (size--)
+    {
+        if (ring->read_index != ring->save_index)
+        {
+            /* read a character */
+            *(ptr++) = ring->buffer[ring->read_index];
+
+            /* move to next position */
+            ring->read_index++;
+            if (ring->read_index >= ring->buffer_size)
+                ring->read_index = 0;
+        }
+        else
+        {
+            break;
+        }
+    }
+ 
+    return (ptr - buffer);
+}
+
+/**********************************************************************************
+** 函数名称:ring_buffer_save
+** 函数功能:保存一个字节
+** 函数参数:无
+** 创建时间:2009-4-23
+** 第一次修改时间:无
+***********************************************************************************/
+void ring_buffer_save_isr(ring_buffer *ring, uint8 dat)
+{
+    /* save character */
+    ring->buffer[ring->save_index] = dat;
+    ring->save_index++;
+    
+    if(ring->save_index >= ring->buffer_size)
+        ring->save_index = 0;
+
+    /* if the next position is read index, discard this 'read char' */
+    if (ring->save_index == ring->read_index)
+    {
+        ring->read_index ++;
+        if(ring->read_index >= ring->buffer_size)
+            ring->read_index = 0;
+    }
+}
+
+/**********************************************************************************
+** 函数名称:ring_buffer_read_isr
+** 函数功能:读取数据
+** 函数参数:无
+** 创建时间:2009-4-23
+** 第一次修改时间:无
+***********************************************************************************/
+int ring_buffer_read_isr(ring_buffer *ring, uint8 *buffer, uint16 size)
+{
+    uint8 *ptr;
+    
+    ptr = buffer;
+    while (size--)
+    {
+        if (ring->read_index != ring->save_index)
+        {
+            /* read a character */
+            *(ptr++) = ring->buffer[ring->read_index];
+
+            /* move to next position */
+            ring->read_index++;
+            if (ring->read_index >= ring->buffer_size)
+                ring->read_index = 0;
+        }
+        else
+        {
+            break;
+        }
+    }
+ 
+    return (ptr - buffer);
+}
+
+/**********************************************************************************
+** 函数名称:ring_buffer_data_num()
+** 函数功能:获取当前缓冲区数据数量
+** 函数参数:无
+** 创建时间:2009-4-23
+** 第一次修改时间:无
+***********************************************************************************/
+uint16 ring_buffer_data_num(ring_buffer *ring)
+{
+    if(ring->save_index >= ring->read_index)
+    {
+        return(ring->save_index - ring->read_index);
+    }
+    else
+    {
+        return(ring->save_index + ring->buffer_size - ring->read_index);
+    }
+}
+
+/**********************************************************************************
+** 函数名称:ring_buffer_isEmpty()
+** 函数功能:判断队列是否空
+** 函数参数:无
+** 创建时间:2009-4-23
+** 第一次修改时间:无
+***********************************************************************************/
+int ring_buffer_isEmpty(ring_buffer *ring)
+{
+    if(ring->save_index == ring->read_index) //判空
+        return TRUE;
+    else
+        return FALSE;
+}
+

+ 29 - 0
src/master/components/ringBuffer/ringBuffer.h

@@ -0,0 +1,29 @@
+#ifndef __RINGBUFFER_H__
+#define __RINGBUFFER_H__
+/*******************************************************************************************************/
+#include "type.h"
+
+typedef struct
+{
+    uint8   *buffer;
+    uint16  buffer_size;
+    uint16  read_index;
+    uint16  save_index;
+} ring_buffer;
+
+/*******************************************************************************************************/
+void ring_buffer_init(ring_buffer *ring, uint8 *buff, uint16 size);
+
+void ring_buffer_save(ring_buffer *ring, uint8 dat);
+int ring_buffer_read(ring_buffer *ring, uint8 *buffer, uint16 size);
+
+void ring_buffer_save_isr(ring_buffer *ring, uint8 dat);
+int ring_buffer_read_isr(ring_buffer *ring, uint8 *buffer, uint16 size);
+
+uint16 ring_buffer_data_num(ring_buffer *ring);
+int ring_buffer_isEmpty(ring_buffer *ring);
+
+#endif
+/*******************************************************************************************************
+**                            End Of File
+********************************************************************************************************/

+ 309 - 0
src/master/user/app/bspatch.c

@@ -0,0 +1,309 @@
+/*-
+ * Copyright 2003-2005 Colin Percival
+ * Copyright 2012 Matthew Endsley
+ * All rights reserved
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted providing that the following conditions 
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <limits.h>
+#include <ustdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "bspatch.h"
+#include "update.h"
+#include "ota.h"
+
+#define WRITE_BLOCK_SIZE    (1024*2)
+
+int64_t offtin(uint8_t *buf)
+{
+    int64_t y;
+
+    y = buf[7]&0x7F;
+    y = y * 256;
+    y += buf[6];
+    y = y * 256;
+    y += buf[5];
+    y = y * 256;
+    y += buf[4];
+    y = y * 256;
+    y += buf[3];
+    y = y * 256;
+    y += buf[2];
+    y = y * 256;
+    y += buf[1];
+    y = y * 256;
+    y += buf[0];
+
+    if (buf[7]&0x80) y = -y;
+
+    return y;
+}
+
+int64_t offtin_32(uint8_t *buf)
+{
+    int64_t y;
+
+    y = buf[3];
+    y = y * 256;
+    y += buf[2];
+    y = y * 256;
+    y += buf[1];
+    y = y * 256;
+    y += buf[0];
+
+    return y;
+}
+
+
+int bspatch(const uint8_t* old, int64_t oldsize, int64_t newsize, struct bspatch_stream* stream)
+{
+    uint8_t buf[8];
+    uint8_t *buf_data;
+    int64_t oldpos, newpos, len;
+    int64_t ctrl[3];
+    int64_t i;
+    uint8_t bk_buf[4];
+    uint32_t bk_len=0,len1=0;
+    
+
+    buf_data = (uint8_t*)malloc(WRITE_BLOCK_SIZE + 1+4);
+    if(buf_data == NULL)return -1;
+    
+    oldpos = 0;
+    newpos = 0;
+    while (newpos < newsize)
+    {
+        /* Read control data */
+        for (i = 0; i <= 2; i++)
+        {
+            if (stream->read(stream, buf, 8))
+                return -1;
+            ctrl[i] = offtin(buf);
+        };
+
+        /* Sanity-check */
+        if (ctrl[0] < 0 || ctrl[0] > INT_MAX ||
+                ctrl[1] < 0 || ctrl[1] > INT_MAX ||
+                newpos + ctrl[0] > newsize)
+            return -1;
+
+        /* Read diff string */
+        while(ctrl[0] > 0)
+        {
+            if(ctrl[0] > WRITE_BLOCK_SIZE)len = WRITE_BLOCK_SIZE;
+            else len = ctrl[0];
+            if (stream->read(stream, buf_data+bk_len, len))return -1;
+            ///
+            if(bk_len)//备份数组长度不为零
+            {
+                memcpy(buf_data,bk_buf,bk_len);
+            }
+            ///
+
+            for (i = 0; i < len; i++)
+            {
+                if ((oldpos + i >= 0) && (oldpos + i < oldsize))
+                {
+                    buf_data[i+bk_len] += old[oldpos + i];
+                }
+            }
+
+            len1 = len+bk_len;
+            if(len1%4)//len长度不是4的整数倍
+            {
+                bk_len = len1%4;
+                memcpy(bk_buf,buf_data+len1-bk_len,bk_len);//剩余的字节备份
+            }
+            else
+            {
+                bk_len = 0;
+            }
+            len1 -= bk_len;
+
+            stream->write(stream, buf_data, len1);
+            ctrl[0] -= len;
+            oldpos += len;
+            newpos += len;
+        }
+
+        /* Sanity-check */
+        if (newpos + ctrl[1] > newsize)
+            return -1;
+
+        /* Read extra string */
+        while(ctrl[1] > 0)
+        {
+            if(ctrl[1] > WRITE_BLOCK_SIZE)len = WRITE_BLOCK_SIZE;
+            else len = ctrl[1];
+            if (stream->read(stream, buf_data+bk_len, len))return -1;
+
+            if(bk_len)
+            {
+                memcpy(buf_data,bk_buf,bk_len);
+            }
+            len1 = len+bk_len;
+            if(len1%4)//len长度不是4的整数倍
+            {
+                bk_len = len1%4;
+                memcpy(bk_buf,buf_data+len1-bk_len,bk_len);//剩余的字节备份
+            }
+            else
+            {
+                bk_len = 0;
+            }
+            len1 -= bk_len;
+
+            stream->write(stream, buf_data, len1);
+            ctrl[1] -= len;
+            newpos += len;
+        }
+
+        /* Adjust pointers */
+        oldpos += ctrl[2];
+        //printk("newpos = %d, ctrl[0] = %ld, ctrl[1] = %ld, ctrl[2] = %ld\n", newpos, ctrl[0], ctrl[1], ctrl[2]);
+    };
+
+    if(buf_data !=NULL)free(buf_data);
+    
+    return 0;
+}
+
+//===========================================================
+#include "lzma_decompress.h"
+#include "type.h"
+#include "ota_flash.h"
+#include "vFile.h"
+
+#define DCOMPRESS_BUFFER_SIZE   (1024*2)
+static uint8_t *diff_data_buff;
+static int diff_data_len, diff_data_fp;
+static int new_data_fp;
+
+static int patch_data_read(const struct bspatch_stream* stream, void* buffer, int length)
+{
+    uint8_t *dp = (uint8_t*)buffer;
+    vFile* pf;
+
+    pf = (vFile*) stream->opaque_r;
+
+    for(int i = 0; i < length; i++)
+    {
+        if(diff_data_len == 0)
+        {
+            diff_data_len = lzma_decompress_read(pf, diff_data_buff, DCOMPRESS_BUFFER_SIZE);
+            if(diff_data_len > 0)
+            {
+                diff_data_fp = 0;
+            }
+            else
+            {
+                return -1;
+            }
+        }
+        if(diff_data_len > 0)
+        {
+            *(dp++) = diff_data_buff[diff_data_fp++];
+            diff_data_len--;
+        }
+    }
+
+    return 0;
+}
+
+static int new_data_write(const struct bspatch_stream* stream, void* buffer, int length)
+{
+    uint32_t file_addr;
+
+    // file_addr = *((uint32_t*)stream->opaque_w);
+    file_addr = 0;
+    
+    //flash_write_without_erase可能因为非对齐访问而报错
+    // if(FALSE == flash_write_without_erase(flash_bak, file_addr + new_data_fp, buffer, length))
+
+    if(FALSE == flash_write_without(ota_info.update_enum, new_data_fp, buffer, length))
+    {
+        // //这个函数支持非对齐写入,但是速度慢
+        // flash_write(flash_bak, file_addr + new_data_fp, buffer, length);
+        printf("length err\n");
+    }
+    new_data_fp += length;
+    printf(".");
+    printf("flash write %d,length:%u\r\n", new_data_fp,length);
+    
+    return(TRUE);
+}
+
+static void patch_data_read_finish(void)
+{
+    lzma_decompress_finish();
+
+}
+
+int iap_patch(const uint8_t* old, uint32_t oldsize, const uint8_t* patch, uint32_t patchsize, uint32_t newfile)
+{
+    vFile *patch_fp;
+    struct bspatch_stream stream;
+    uint8_t header[20];//将24改为20
+    int64_t newsize;
+
+    //初始化全局变量
+    diff_data_len = 0;
+    diff_data_fp = 0;
+    new_data_fp = 0;
+    patch_fp = vfopen(patch, patchsize);
+    
+    //读取差分文件头
+    vfread(patch_fp, header, sizeof(header));
+    if (memcmp(header, "ENDSLEY/BSDIFF43", 16) != 0)return(0);
+    //计算新固件长度
+    newsize = offtin_32(header + 16);
+    if(newsize < 0)return(0);
+    
+    //分配内存
+    diff_data_buff = malloc(DCOMPRESS_BUFFER_SIZE);
+    if(diff_data_buff == NULL)return(0);
+    
+    //准备合并文件
+    stream.read = patch_data_read;
+    stream.opaque_r = (void*)patch_fp;
+    stream.write = new_data_write;
+    stream.opaque_w = &newfile;
+    
+    bspatch(old, oldsize, newsize, &stream);
+    
+    //释放内存
+    patch_data_read_finish();
+    free(diff_data_buff);
+    vfclose(patch_fp);
+    
+    return((int)newsize);
+}
+
+
+
+
+
+
+
+

+ 47 - 0
src/master/user/app/bspatch.h

@@ -0,0 +1,47 @@
+/*-
+ * Copyright 2003-2005 Colin Percival
+ * Copyright 2012 Matthew Endsley
+ * All rights reserved
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted providing that the following conditions 
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef BSPATCH_H
+# define BSPATCH_H
+
+# include <stdint.h>
+
+struct bspatch_stream
+{
+	void* opaque_r;
+	int (*read)(const struct bspatch_stream* stream, void* buffer, int length);
+        
+    void* opaque_w;
+	int (*write)(const struct bspatch_stream* stream, void* buffer, int length);
+};
+
+int64_t offtin(uint8_t *buf);
+int bspatch(const uint8_t* old, int64_t oldsize, int64_t newsize, struct bspatch_stream* stream);
+int iap_patch(const uint8_t* old, uint32_t oldsize, const uint8_t* patch, uint32_t patchsize, uint32_t newfile);
+
+#endif
+

+ 479 - 0
src/master/user/app/iap.c

@@ -0,0 +1,479 @@
+/**
+  ******************************************************************************
+  * @file    iap.c
+  * @author  eming
+  * @version V1.0.0
+  * @date    2022-03-21
+  * @brief   IAP程序,支持压缩格式固件和差分升级
+  ******************************************************************************
+  */  
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <stdlib.h>
+#include "usr_cfg.h"
+// #include "stm32f10x.h"
+// #include "core_cm3.h"
+#include "bsp.h"
+#include "ota_flash.h"
+// #include "sys_time.h"
+#include "mylib.h"
+#include "db.h"
+#include "iap.h"
+// #include "shell.h"
+#include "lzma_decompress.h"
+#include "crc32.h"
+#include "bspatch.h"
+#include "vFile.h"
+
+/*************************************************************/
+#define IH_MAGIC   0x27051956   /* Image Magic Number       */
+#define IH_NMLEN   (32 - 4)     /* Image Name Length        */
+
+typedef struct image_header 
+{
+    uint32_t ih_magic;/* Image Header Magic Number     */
+    uint32_t ih_hcrc; /* Image Header CRC Checksum     */
+    uint32_t ih_time; /* Image Creation Timestamp */
+    uint32_t ih_size; /* Image Data Size     */
+    uint32_t ih_load; /* Data Load Address         */
+    uint32_t ih_ep;   /* Entry Point Address      */
+    uint32_t ih_dcrc; /* Image Data CRC Checksum */
+    uint8_t  ih_os;   /* Operating System         */
+    uint8_t  ih_arch; /* CPU architecture         */
+    uint8_t  ih_type; /* Image Type          */
+    uint8_t  ih_comp; /* Compression Type         */
+    uint8_t  ih_name[IH_NMLEN]; /* Image Name      */
+    uint32_t ih_ocrc; /* Old Image Data CRC Checksum */ 
+} image_header_t;
+
+#define UIMAGE_HEADER_LEN   sizeof(image_header_t)
+#define UIMAGE_MAX_LEN      (0x80000) 
+
+/**
+ * @brief 擦除FLASH
+ * @details 擦除下载的flash分区
+ *
+ * @param 无
+ * @return 无
+ *   @retval 无
+ */
+void iap_download_flash_erase(void)
+{
+    // flash_partition_erase(flash_bak, 0, FLASH_BAK_SIZE);
+}
+
+/**
+ * @brief 下载数据
+ * @details 下载数据到备份分区
+ *
+ * @param offset 数据偏移量
+ * @param datp 数据指针
+ * @param datp 数据长度
+ * @return 操作结果
+ *   @retval 略
+ */
+int iap_download(uint32_t offset, uint8_t *datp, uint16_t len)
+{
+    // flash_write_without_erase(flash_bak, offset, datp, len);
+
+    return(TRUE);
+}
+
+/**
+ * @brief 检查镜像
+ * @details 根据头部信息校验数据,并返回头
+ *
+ * @param part flash分区
+ * @return 操作结果
+ *   @retval 略
+ */
+static int iap_uimage_check(uint32_t addr, image_header_t *ih)
+{
+    uint32_t magic, size, dcrc, crc;
+    int ret = FALSE;
+    
+    memcpy(ih, (void *)addr, UIMAGE_HEADER_LEN);
+    magic = BigtoLittle32(ih->ih_magic);
+    size  = BigtoLittle32(ih->ih_size);
+    dcrc = BigtoLittle32(ih->ih_dcrc);
+    
+    if((magic == IH_MAGIC) && (size <= UIMAGE_MAX_LEN))
+    {
+        // crc = flash_crc(addr + UIMAGE_HEADER_LEN, size);
+        // if(crc == dcrc)
+        // {
+        //     ret = TRUE;
+        // }
+    }
+    
+    return(ret);
+}
+    
+/**
+ * @brief 修改固件镜像
+ * @details 覆盖固件或者打差分补丁
+ *
+ * @param 无
+ * @return 操作结果
+ *   @retval 略
+ */
+int iap_image_patch(void)
+{
+    image_header_t ih;
+    uint32_t uimage_addr;
+    uint32_t size, dcrc, crc, ocrc;
+    uint32_t app_addr, image_len, unpk_len;
+    uint8_t *image_p, *patch_p;
+    uint8_t *buff;
+    vFile* vfp;
+    uint32_t old_size;
+    
+    // flash_partition_addr(flash_bak, &uimage_addr);
+    if(TRUE == iap_uimage_check(uimage_addr, &ih))
+    {
+        size  = BigtoLittle32(ih.ih_size);
+        dcrc = BigtoLittle32(ih.ih_dcrc);
+        image_len = size + UIMAGE_HEADER_LEN;
+        /*
+        ** 镜像类型:1,standalone; 2,kernel; 3,ramdisk; 4,multi; 5,firmware; 6,script; 7,filesystem; 8,diffpatch
+        */
+        if(ih.ih_type == 2)
+        {
+            /*
+            ** 压缩类型:0,none; 1,gzip; 2,bzip2; 3,lzma
+            */
+            if(ih.ih_comp == 0) //未压缩镜像,直接覆写,mkuzimage -O rtos -T kernel -a 0x0800FFC0 -e 0x08010000 -i image.bin -o uimage.bin
+            {
+                // flash_partition_erase(flash_app, 0, FLASH_APP_SIZE);   //擦除APP
+                // //写镜像数据
+                // image_p = flash_read_fp(flash_bak, IAP_BAK_ADDR);
+                // flash_write_without_erase(flash_app, 0, image_p, size + UIMAGE_HEADER_LEN);
+                // //覆写完成,计算数据CRC
+                // crc = flash_partition_crc(flash_app, 0 + UIMAGE_HEADER_LEN, size);
+                // if(crc == dcrc)
+                // {
+                //     return(TRUE);
+                // }
+            }
+            else if(ih.ih_comp == 3)    //LZMA压缩,mkuzimage -O rtos -T kernel -C lzma -a 0x0800FFC0 -e 0x08010000 -i image.bin -o uzimage.bin
+            {
+                // //分配内存
+                // buff = (uint8_t *)malloc(FLASH_PAGE_SIZE);
+                // if(NULL == buff)return(FALSE);
+                // flash_partition_erase(flash_app, 0, FLASH_APP_SIZE);   //擦除APP
+                // //解压uzimage的数据段
+                // image_p = flash_read_fp(flash_bak, IAP_BAK_ADDR + UIMAGE_HEADER_LEN);
+                // vfp = vfopen(image_p, size);
+                // app_addr = UIMAGE_HEADER_LEN;
+                // image_len = 0;
+                // while(1)
+                // {
+                //     unpk_len = lzma_decompress_read(vfp, buff, FLASH_PAGE_SIZE);
+                //     if(unpk_len == 0)break;
+                //     flash_write_without_erase(flash_app, app_addr, buff, unpk_len);
+                //     app_addr += unpk_len;
+                //     image_len += unpk_len;
+                // }
+                // free(buff);
+                // //最后写入文件头
+                // crc = flash_partition_crc(flash_app, 0 + UIMAGE_HEADER_LEN, image_len);
+                // ih.ih_size = BigtoLittle32(image_len);
+                // ih.ih_dcrc = BigtoLittle32(crc);
+                // crc = crc32((unsigned char*)&ih, UIMAGE_HEADER_LEN);
+                // ih.ih_hcrc = BigtoLittle32(crc);
+                // ih.ih_comp = 0;
+                // flash_write_without_erase(flash_app, 0, &ih, UIMAGE_HEADER_LEN);
+                
+                return(TRUE);
+            }
+            else    //未支持的压缩类型
+            {    
+                return(FALSE);
+            }
+        }
+        else if(ih.ih_type == 8)    //差分升级包:mkuzimage -O rtthread -T diffpatch -C lzma -a 0 -e 0 -i diff.bin -o udiff.bin
+        {
+            if(ih.ih_comp == 3)     //LZMA压缩
+            {
+                ocrc = BigtoLittle32(ih.ih_ocrc);
+                // //校验老固件的完整性
+                // flash_partition_addr(flash_app, &uimage_addr);
+                // if(TRUE == iap_uimage_check(uimage_addr, &ih))
+                // {
+                //     dcrc = BigtoLittle32(ih.ih_dcrc);
+                //     if(dcrc == ocrc)    //检查补丁包的ocrc值是否等于老固件的dcrc
+                //     {
+                //         old_size  = BigtoLittle32(ih.ih_size);
+                //         //将差分包和APP合并,数据保存到备份区
+                //         flash_partition_erase(flash_bak, IAP_DIFF_NEW_ADDR, FLASH_BAK_SIZE - IAP_DIFF_NEW_ADDR);
+                //         image_p = flash_read_fp(flash_app, 0 + UIMAGE_HEADER_LEN);
+                //         patch_p = flash_read_fp(flash_bak, IAP_BAK_ADDR);
+                //         image_len = iap_patch(image_p, old_size, patch_p + UIMAGE_HEADER_LEN, size, IAP_DIFF_NEW_ADDR + UIMAGE_HEADER_LEN);
+                //         //更新文件头信息
+                //         crc = flash_partition_crc(flash_bak, IAP_DIFF_NEW_ADDR + UIMAGE_HEADER_LEN, image_len);
+                //         ih.ih_size = BigtoLittle32(image_len);
+                //         ih.ih_dcrc = BigtoLittle32(crc);
+                //         crc = crc32((unsigned char*)&ih, UIMAGE_HEADER_LEN);
+                //         ih.ih_hcrc = BigtoLittle32(crc);
+                //         flash_write_without_erase(flash_bak, IAP_DIFF_NEW_ADDR, &ih, UIMAGE_HEADER_LEN);
+                        
+                //         //擦除老固件
+                //         flash_partition_erase(flash_app, 0, FLASH_APP_SIZE);
+                //         //写镜像数据
+                //         image_p = flash_read_fp(flash_bak, IAP_DIFF_NEW_ADDR);
+                //         flash_write_without_erase(flash_app, 0, image_p, image_len + UIMAGE_HEADER_LEN);
+                        
+                //         return(TRUE);                        
+                //     }                    
+                // }
+                // else
+                // {
+                //     //出现这种情况,可能是新固件覆写时,由于断电或者复位导致老固件数据被破坏了,重新写入
+                //     flash_partition_addr(flash_bak, &uimage_addr);
+                //     if(TRUE == iap_uimage_check(uimage_addr + IAP_DIFF_NEW_ADDR, &ih))
+                //     {
+                //         image_len  = BigtoLittle32(ih.ih_size);
+                //         //擦除老固件
+                //         flash_partition_erase(flash_app, 0, FLASH_APP_SIZE);
+                //         //写镜像数据
+                //         image_p = flash_read_fp(flash_bak, IAP_DIFF_NEW_ADDR);
+                //         flash_write_without_erase(flash_app, 0, image_p, image_len + UIMAGE_HEADER_LEN);
+                        
+                //         return(TRUE); 
+                //     }
+                // }
+            }
+        }
+    }
+
+    return(FALSE);
+}
+
+/**
+ * @brief 升级固件
+ * @details 检查升级标志,有效则进入升级
+ *
+ * @param 无
+ * @return 操作结果
+ *   @retval 略
+ */
+int iap_upgrade(void)
+{
+    IAP_AppBak_stk file_bak;
+
+    db_read(&file_bak, DB_APPBAK);        //读取升级数据信息
+
+    if(IAP_MAGIC_FLG == file_bak.flg)     //检查升级标志
+    {
+        // printk("upgrade beginning!\r\n");
+        if(TRUE == iap_image_patch())
+        {
+            //更新下载区信息
+            file_bak.flg = 0xFFFF;
+            db_write(&file_bak, DB_APPBAK);
+            // printk("\r\nupgrade done!\r\n");
+            
+            return(TRUE);            
+        }
+        else
+        {
+            // printk("upgrade failure!\r\n");
+        }
+    }
+    return(FALSE);
+}
+
+/**
+ * @brief 加载到APP
+ * @details 跳转到指定地址运行程序
+ *
+ * @param entry 入口地址
+ * @return 操作结果
+ *   @retval 无
+ */
+void iap_boot_app(uint32_t entry)
+{
+    typedef void (*pFunction)(void);
+    pFunction Jump_To_Application;
+    uint32_t 	JumpAddress;
+    
+    if (((*(volatile uint32_t *)entry) & 0x2FFE0000 ) == 0x20000000)
+    {
+        // //释放使用的硬件外设
+        // board_deinit();
+        // __disable_irq();
+        
+        // //跳转至用户代码
+        // JumpAddress = *(volatile uint32_t *) (entry + 4);
+        // Jump_To_Application = (pFunction) JumpAddress;
+
+        // //初始化用户程序的堆栈指针
+        // __set_MSP(*(volatile uint32_t *) entry);
+        // Jump_To_Application();
+        
+        while(1);
+    }
+}
+
+/**
+ * @brief 加载镜像
+ * @details 检查镜像头,CRC校验,合法则加载镜像
+ *
+ * @param 无
+ * @return 操作结果
+ *   @retval 略
+ */
+static int iap_load_uimage(void)
+{
+    image_header_t ih;
+    uint32_t uimage_addr;
+
+    // flash_partition_addr(flash_app, &uimage_addr); 
+    // if(TRUE == iap_uimage_check(uimage_addr, &ih))
+    // {
+    //     printk("find image %s...\r\n", ih.ih_name);
+    //     iap_boot_app(FLASH_APP_BASE + UIMAGE_HEADER_LEN);
+    // }
+    // else
+    // {
+    //     printk("image file crc check failure!\r\n");
+    // }
+
+    return(FALSE);
+}
+
+/**
+ * @brief IAP主程序
+ * @details 3S内可被中断流程
+ *
+ * @param 无
+ * @return 操作结果
+ *   @retval 无
+ */
+static int iap_task_ps = 0;
+void iap_task(void)
+{
+    static int iap_task_delay;
+    
+    switch(iap_task_ps)
+    {
+    case 0:
+        iap_task_delay = 1;
+        // printk("Hit any key to stop autoboot: %d", iap_task_delay);
+        iap_task_ps = 1;
+        break;
+    
+    case 1:
+        iap_task_delay--;
+        // printk("\b");
+        // printk("%d", iap_task_delay);    
+        if(iap_task_delay <= 0)
+        {
+            // printk("\r\n");
+            iap_task_ps = 2;
+        }
+        break;
+    
+    case 2:
+        iap_upgrade();
+        //加载进入应用程序
+        // printk("boot from flash...\r\n");
+        if(FALSE == iap_load_uimage())
+        {
+            // printk("boot failure!\r\n");
+            iap_task_ps = 0xFF;
+        }        
+        break;
+        
+    case 0xFF:
+    default:
+        break;
+    }
+}
+
+/**
+ * @brief 退出IAP
+ * @details 无
+ *
+ * @param 无
+ * @return 无
+ *   @retval 无
+ */
+void iap_quit(void)
+{
+    iap_task_ps = 0xFF;
+}
+
+/**
+ * @brief 下载数据结束
+ * @details 校验数据,并写入升级标志
+ *
+ * @param 无
+ * @return 无
+ *   @retval 无
+ */
+void iap_download_done(void)
+{
+    image_header_t ih;
+    uint32_t magic;
+    IAP_AppBak_stk 	file_bak;
+    
+    // flash_read(flash_bak, IAP_BAK_ADDR, (uint8_t*)&ih, UIMAGE_HEADER_LEN);
+    magic = BigtoLittle32(ih.ih_magic);
+    
+    if(magic == IH_MAGIC)
+    {
+        file_bak.flg = IAP_MAGIC_FLG;     //升级标志
+        db_write(&file_bak, DB_APPBAK);
+    } 
+}
+
+/**
+ * @brief IAP测试用例
+ * @details 手动进入IAP模式
+ *
+ * @param 无
+ * @return 无
+ *   @retval 无
+ */
+void iap_upgrade_start(void)
+{
+    iap_download_done();   
+}
+
+#if CONFIG_SHELL_ENABLE
+/**
+ * @brief 直接跳转到指定地址
+ * @details shell命令,用于调试
+ *
+ * @param arg 操作命令字符串
+ * @return 操作结果
+ *   @retval 略
+ */
+int bootm(void *arg)
+{
+    static const char tips[] = "bootm [entry, eg 0x8008000]\r\n";
+    char *argv[2];
+    uint32_t entry;
+    // int argc = cmdline_strtok((char *)arg, argv, 2);
+    
+    // if(argc < 2)
+    // {
+    //     printl((char *)tips, sizeof(tips) - 1);
+    //     entry = 0x8008000;
+    // }
+    // else
+    // {
+    //     entry = htoi(argv[1]);
+    // }
+    iap_boot_app(entry);
+    
+    return 0;
+}
+#endif
+
+/*******************************************************************************************************
+**                            End Of File
+********************************************************************************************************/
+

+ 33 - 0
src/master/user/app/iap.h

@@ -0,0 +1,33 @@
+#ifndef __IAP_H__
+#define __IAP_H__
+/*******************************************************************************************************/
+#define IAP_BAK_ADDR        0               //APP备份镜像保存位置
+
+#ifdef FLASH_SIZE_256K
+#define IAP_DIFF_NEW_ADDR   (28 * 1024)     //差分升级时,合并后文件保存地址
+#else
+#define IAP_DIFF_NEW_ADDR   (60 * 1024)     //差分升级时,合并后文件保存地址
+#endif
+
+#define IAP_MAGIC_FLG       (0xAA55)        //APP升级标志
+
+/*******************************************************************************************************/
+#include "stdint.h"
+
+typedef struct
+{
+    uint16_t flg;            //升级标志
+} IAP_AppBak_stk;
+
+/*******************************************************************************************************/
+void iap_download_flash_erase(void);
+int  iap_download(uint32_t offset, uint8_t *datp, uint16_t len);
+void iap_download_done(void);
+void iap_upgrade_start(void);
+void iap_task(void);
+void iap_quit(void);
+
+#endif
+/*******************************************************************************************************
+**                            End Of File
+********************************************************************************************************/

+ 536 - 0
src/master/user/app/ota_flash.c

@@ -0,0 +1,536 @@
+/**
+  ******************************************************************************
+  * @file    flash.c
+  * @author  eming
+  * @version V1.0.0
+  * @date    2021-09-19
+  * @brief   内部FLASH初始化.
+  ******************************************************************************
+  */
+#include <string.h>
+#include <stdlib.h>
+#include "ustdio.h"
+#include "usr_cfg.h"
+#include "type.h"
+#include "ota_flash.h"
+#include "mylib.h"
+#include "myflash.h"
+#include "flash.h"
+
+
+/*************************************************************/
+extern void IWDG_feed(void);
+// extern void Flash_BufferWrite(uint32_t address, uint32_t *p_buffer, uint32_t len);
+
+/**
+ * @brief 获取FLASH数据地址
+ * @details 将FALSH分区地址转换为物理地址
+ *
+ * @param  part 分区号
+ * @param  addr 分区内数据相对地址
+ * @param  len 要操作的数据长度
+ * @param  *phy_addr 返回的物理地址
+ * @return 操作的数据是否在分区内
+ *   @retval TRUE 合法的操作
+ *   @retval FALSE 非法的操作
+ */
+static int flash_addr(flash_partition_enum part, uint32_t addr, uint32_t len, uint32_t *phy_addr)
+{
+    switch(part)                               //检查存储类型
+    {
+    case flash_boot:
+        if((addr + len) > FLASH_BOOT_SIZE)return(FALSE);
+        *phy_addr = FLASH_BOOT_BASE + addr;
+        break;
+
+    case flash_app:
+        if((addr + len) > FLASH_APP_SIZE)return(FALSE);
+        *phy_addr = FLASH_APP_BASE + addr;
+        break;
+    
+    case flash_bak:
+        if((addr + len) > FLASH_BAK_SIZE)return(FALSE);
+        *phy_addr = FLASH_BAK_BASE + addr;
+        break;    
+
+    case flash_cfg:
+        if((addr + len) > FLASH_CFG_SIZE)return(FALSE);
+        *phy_addr = FLASH_CFG_BASE + addr;
+        break;
+
+    default:
+        return(FALSE);
+    }
+    return(TRUE);
+}
+
+/**
+ * @brief 获取分区起始地址
+ * @details 获取指定分区的起始地址
+ *
+ * @param  part 分区号
+ * @return 分区起始地址
+ *   @retval 无
+ */
+int flash_partition_addr(flash_partition_enum part, uint32_t *addr)
+{
+    int ret = TRUE;
+    
+    switch(part)                               //检查存储类型
+    {
+    case flash_boot:
+        *addr = FLASH_BOOT_BASE;
+        break;
+
+    case flash_app:
+        *addr = FLASH_APP_BASE;
+        break;
+    
+    case flash_bak:
+        *addr = FLASH_BAK_BASE;
+        break;    
+
+    case flash_cfg:
+        *addr = FLASH_CFG_BASE;
+        break;
+    
+    default:
+        ret = FALSE;
+        break;
+    }
+    
+    return(ret);
+}
+
+/**
+ * @brief 获取分区大小
+ * @details 获取指定分区的字节数
+ *
+ * @param  part 分区号
+ * @return 分区大小
+ *   @retval 无
+ */
+uint32_t flash_partition_size(flash_partition_enum part)
+{
+    uint32_t size = 0;
+    
+    switch(part)                               //检查存储类型
+    {
+    case flash_boot:
+        size = FLASH_BOOT_SIZE;
+        break;
+
+    case flash_app:
+        size = FLASH_APP_SIZE;
+        break;
+    
+    case flash_bak:
+        size = FLASH_BAK_SIZE;
+        break;    
+
+    case flash_cfg:
+        size = FLASH_CFG_SIZE;;
+        break;
+    }
+    
+    return(size);
+}
+
+/**
+ * @brief 按页写数据
+ * @details 写入整页数据
+ *
+ * @param  page_addr 页地址,4字节对齐
+ * @param  *datp 数据指针
+ * @return 操作结果
+ *   @retval 无
+ */
+static int flash_page_write(uint32_t page_addr, uint8_t *datp)
+{
+    volatile uint32_t *fls_p;
+    uint32_t i, word;
+    U32_U8 dat;
+
+    page_addr &= 0xFFFFFFFC;
+    fls_p 	 = (volatile uint32_t *)page_addr;
+    for(i = 0; i < FLASH_PAGE_WORD; i++)	  //写入数据
+    {
+        dat.d8[0] = *(datp++);
+        dat.d8[1] = *(datp++);
+        dat.d8[2] = *(datp++);
+        dat.d8[3] = *(datp++);
+        word = *(fls_p++);
+        if((dat.d32 != word) && (word == 0xFFFFFFFF))
+        {
+            Flash_BufferWrite(page_addr,&dat.d32,4);//按字写入
+            // FLASH_ProgramWord(page_addr, dat.d32); //按字写入
+        }
+        page_addr += 4;
+    }
+    return(TRUE);
+}
+
+/**
+ * @brief 按页读数据
+ * @details 读出整页数据
+ *
+ * @param  page_addr 页地址,4字节对齐
+ * @param  *datp 数据指针
+ * @return 页大小
+ *   @retval 无
+ */
+static int flash_page_read(uint32_t page_addr, uint8_t *datp)
+{
+    volatile uint32_t *fls_p;
+    uint32_t i, *dp32;
+
+    page_addr &= 0xFFFFFFFC;
+    fls_p  = (volatile uint32_t *)page_addr;
+    // dp32   = (uint32_t *)datp;
+    for(i = 0; i < FLASH_PAGE_WORD; i++)			//读取数据
+    {
+        *(dp32++) = *(fls_p++);
+    }
+    
+    return(FLASH_PAGE_SIZE);
+}
+
+/**
+ * @brief 扇区擦除
+ * @details 扇区擦除,支持非扇区对齐
+ *
+ * @param  addr,起始地址
+ * @param  len,擦除的数据块长度
+ * @return erase_len 本扇区擦除的长度,可能小于len
+ *   @retval 无 
+ */
+static uint32_t flash_page_erase(uint32_t addr, uint32_t len)
+{
+    uint32_t page_addr, offset;
+    uint8_t  *buff;
+    uint32_t erase_len;
+    
+    offset = addr % FLASH_PAGE_SIZE;        //计算是否扇区对齐
+    erase_len = FLASH_PAGE_SIZE - offset;   //本扇区可擦除的长度
+    if(erase_len > len)erase_len = len;
+    
+    //如果擦除长度小于扇区长度,说明有数据需要保留
+    if(erase_len < FLASH_PAGE_SIZE)
+    {
+        //申请内存
+        buff = (uint8_t *)malloc(FLASH_PAGE_SIZE);
+        if(NULL == buff)return(FALSE);
+        page_addr = addr - offset;
+        flash_page_read(page_addr, buff);	//读取数据
+        // FLASH_ErasePage(addr);
+        memset(buff + offset, 0xFF, erase_len);
+        flash_page_write(page_addr, buff); //写入数据
+        free(buff);
+    }
+    else
+    {
+        // FLASH_ErasePage(addr);
+        erase_len = FLASH_PAGE_SIZE;
+    }
+    
+    return(erase_len);
+}
+
+/**
+ * @brief 分区擦除
+ * @details 擦除整个分区,类似硬盘格式化
+ *
+ * @param  part 分区号
+ * @param  addr,起始地址
+ * @param  size,擦除的数据块长度
+ * @return 操作结果
+ *   @retval 无 
+ */
+int flash_partition_erase(flash_partition_enum part, uint32_t addr, uint32_t size)
+{
+    uint32_t part_addr;
+    uint32_t erase_len;
+
+    if(FALSE == flash_addr(part, addr, size, &part_addr))return(FALSE);
+    
+    // FLASH_Unlock();
+    
+    while(size > 0)
+    {
+        erase_len = flash_page_erase(part_addr, size);
+        part_addr += erase_len;
+        size -= erase_len;
+        IWDG_feed();
+    }
+    
+    // FLASH_Lock();
+    
+    return(TRUE);
+}
+
+/**
+ * @brief 分区数据写入
+ * @details 当前分区数据写入,不支持非对齐写入
+ *
+ * @param  part 分区号
+ * @param  addr 相对地址
+ * @param  p 数据指针
+ * @param  len 数据长度
+ * @return 操作结果
+ *   @retval 无 
+ */
+int flash_write_without_erase(flash_partition_enum part, uint32_t addr, const void *p, uint32_t len)
+{
+    uint32_t phy_addr;
+    U32_U8 dat;
+    uint8_t *datp = (uint8_t*)p;
+    int i;    
+    
+    if(FALSE == flash_addr(part, addr, len, &phy_addr))return(FALSE);
+    
+    IWDG_feed();
+    FLASH_Unlock();
+    if((phy_addr % 4) != 0)
+    {
+        return(FALSE);
+    }
+    
+    while(len)
+    {
+        dat.d32 = 0xFFFFFFFF;
+        for(i = 0; i < 4; i++)
+        {
+            if(len > 0)
+            {
+                dat.d8[i] = *(datp++);
+                len--;
+            }
+        }
+        // FLASH_ProgramWord(phy_addr, dat.d32); //按字写入
+        FLASH_FastProgram(phy_addr, dat.d32, 4);//按字写入
+        phy_addr += 4;
+        //每写入1K数据,喂一次狗
+        if(0 == (phy_addr & 0x3FF))
+        {
+            IWDG_feed();
+        }
+    }
+    FLASH_Lock();
+    
+    return(TRUE);
+}
+    
+/**
+ * @brief 分区数据写入
+ * @details 当前分区数据写入,支持非对齐写入,写之前不需要擦除
+ *
+ * @param  part 分区号
+ * @param  addr 相对地址
+ * @param  p 数据指针
+ * @param  len 数据长度
+ * @return 操作结果
+ *   @retval 无 
+ */
+int flash_write(flash_partition_enum part, uint32_t addr, const void *p, uint32_t len)
+{
+    uint32_t pg, pd, offset;
+    uint32_t page_addr, phy_addr;
+    uint8_t  *buff;
+    uint8_t *datp = (uint8_t*)p;
+
+    if(FALSE == flash_addr(part, addr, len, &phy_addr))return(FALSE);
+
+    IWDG_feed();
+    //申请内存
+    buff = (uint8_t *)malloc(FLASH_PAGE_SIZE);
+    if(NULL == buff)
+    {
+        printk("FLASH:memory allocation failure...\r\n");
+        return(FALSE);
+    }
+
+    FLASH_Unlock();							    //解锁FLASH编写擦除控制器
+    pg = phy_addr / FLASH_PAGE_SIZE;            //计算扇区号
+    offset = phy_addr % FLASH_PAGE_SIZE;        //计算扇区内偏移
+    pd = FLASH_PAGE_SIZE - offset;          	//计算当前地址所在的扇区还可以写多少字节
+    if(len <= pd)pd = len;                 		//判断数据是否在当前页内
+    page_addr = pg * FLASH_PAGE_SIZE;	        //计算扇区物理地址
+    flash_page_read(page_addr, buff);		    //读取数据
+
+    //判断要写入的区域是否为0xFF
+    if((FALSE == mylib_memcmp_b(buff + offset, 0xFF, pd)) || (offset % 4))
+    {
+        // FLASH_ErasePage(page_addr);		    //擦除一个扇区
+    }
+    memcpy(buff + offset, datp, pd);		    //修改数据
+    flash_page_write(page_addr, buff);		    //写入数据
+
+    len -= pd;                         		    //判断剩下的数据长度
+    datp += pd;                                 //移动数据指针
+    while(len)                            		//如果没有写完,写到下一页
+    {
+        pg++;                           		//扇区号指向下一扇区
+        page_addr = pg * FLASH_PAGE_SIZE;	    //计算物理地址
+        if(len >= FLASH_PAGE_SIZE)            	//如果剩下的数据大于扇区长度
+        {
+            flash_page_read(page_addr, buff);  //读取该扇区
+            //判断要写入的区域是否为0xFF
+            if(FALSE == mylib_memcmp_b(buff, 0xFF, FLASH_PAGE_SIZE))
+            {
+                // FLASH_ErasePage(page_addr);    //擦除一个扇区
+            }
+            flash_page_write(page_addr, datp); //写入数据
+            len -= FLASH_PAGE_SIZE;
+            datp += FLASH_PAGE_SIZE;
+        }
+        else
+        {
+            flash_page_read(page_addr, buff);  //读取该扇区
+            //判断要写入的区域是否为0xFF
+            if(FALSE == mylib_memcmp_b(buff, 0xFF, len))
+            {
+                // FLASH_ErasePage(page_addr);    //擦除一个扇区
+            }
+            memcpy(buff, datp, len);            //修改数据
+            flash_page_write(page_addr, buff); //写入数据
+            len = 0;
+        }
+    }
+    FLASH_Lock();
+    free(buff);
+    
+    return(TRUE);
+}
+
+/**
+ * @brief 分区数据读取
+ * @details 当前分区数据读取,M3支持字节对齐访问
+ *
+ * @param  part 分区号
+ * @param  addr 相对地址
+ * @param  p 数据指针
+ * @param  len 数据长度
+ * @return 操作结果
+ *   @retval 无 
+ */
+int flash_read(flash_partition_enum part, uint32_t addr, void *p, uint32_t len)
+{
+    uint32_t phy_addr;
+    uint8_t *datp;
+    volatile uint8_t *fls_p;
+
+    if(FALSE == flash_addr(part, addr, len, &phy_addr))return(FALSE);
+    fls_p = (volatile uint8_t *)phy_addr;
+    datp = (uint8_t*)p;
+
+    while(len)
+    {
+        *(datp++) = *(fls_p++);
+        len--;
+    }
+    return(TRUE);
+}
+
+/**
+ * @brief 直接获取分区数据操作指针
+ * @details 当前分区数据访问,M3支持字节对齐
+ *
+ * @param  part 分区号
+ * @param  addr 相对地址
+ * @return 数据指针
+ *   @retval 无 
+ */
+uint8_t* flash_read_fp(flash_partition_enum part, uint32_t addr)
+{
+    uint32_t phy_addr;
+    uint8_t *fls_p;
+    
+    if(FALSE == flash_addr(part, addr, 0, &phy_addr))return(NULL);
+    fls_p = (uint8_t *)phy_addr;
+    
+    return(fls_p);
+}
+
+/**
+ * @brief 计算和校验
+ * @details 计算当前分区数据块和校验
+ *
+ * @param  part 分区号
+ * @param  addr 数据起始地址
+ * @param  len 数据长度
+ * @return 和校验结果
+ *   @retval 无 
+ */
+uint32_t flash_sum(uint32_t addr, uint32_t len)
+{
+    uint32_t sum;
+    volatile uint8_t *fls_p;
+
+    fls_p = (volatile uint8_t *)addr;
+    
+    sum = 0;
+    while(len--)
+    {
+        sum += *(fls_p++);
+        if(0 == (len & 0x3FF))			//每校验1K数据,喂一次狗
+        {
+            IWDG_feed();
+        }
+    }
+    return(FALSE);
+}
+
+/**
+ * @brief 计算CRC32校验
+ * @details 计算当前地址数据块CRC32校验
+ *
+ * @param  addr 数据起始地址
+ * @param  len 数据长度
+ * @return CRC32校验结果
+ *   @retval 无 
+ */
+extern const unsigned int crc32tab[];
+uint32_t flash_crc(uint32_t addr, uint32_t len)
+{
+    volatile uint8_t *fls_p;
+    uint32_t crc;
+    
+    fls_p = (volatile uint8_t *)addr;
+    
+    crc = 0xFFFFFFFF;
+    while(len--)
+    {
+        //计算CRC
+        crc = crc32tab[(crc ^ (*(fls_p++))) & 0xff] ^ (crc >> 8);
+        if(0 == (len & 0x3FF))			//每校验1K数据,喂一次狗
+        {
+            IWDG_feed();
+        }
+    }
+    
+    return crc ^ 0xFFFFFFFF;
+}
+
+/**
+ * @brief 计算CRC32校验
+ * @details 计算当前分区数据块CRC32校验
+ *
+ * @param  part 分区号
+ * @param  addr 数据起始地址
+ * @param  len 数据长度
+ * @return CRC32校验结果
+ *   @retval 无 
+ */
+uint32_t flash_partition_crc(flash_partition_enum part, uint32_t addr, uint32_t len)
+{
+    uint32_t phy_addr;
+    
+    if(FALSE == flash_addr(part, addr, len, &phy_addr))return(FALSE);
+    
+    return flash_crc(phy_addr, len);
+}
+
+/*******************************************************************************************************
+**                            End Of File
+********************************************************************************************************/
+

+ 82 - 0
src/master/user/app/ota_flash.h

@@ -0,0 +1,82 @@
+#ifndef __FLASH_H__
+#define __FLASH_H__
+/*******************************************************************************************************/
+#include "stdint.h"
+
+
+#ifndef FLASH_PAGE_SIZE
+#define FLASH_PAGE_SIZE			(256)              //FLASH页大小,必须字对齐
+#endif
+
+#define FLASH_SIZE_1024K
+#define FLASH_PAGE_WORD			(512)               //FLASH页大小,字长度
+
+#ifdef FLASH_SIZE_256K
+//FLASH分区
+#define FLASH_BOOT_BASE    		(0x08000000)        //bootloader起始地址,32K - 64B
+#define FLASH_APP_BASE    		(0x08007FC0)        //应用程序起始地址,64B + 96KB
+#define FLASH_APP_ENTRY         (0x08008000)        //应用程序入口
+#define FLASH_BAK_BASE    		(0x08020000)        //数据后备区
+#define FLASH_CFG_BASE          (0x0807F000)        //252K-256K,保存一些重要的配置信息,4K
+
+#define FLASH_BOOT_SIZE			(32 * 1024 - 64)    //bootloader长度
+#define FLASH_APP_SIZE			(96 * 1024 + 64)    //应用程序长度
+#define FLASH_BAK_SIZE			(124 * 1024)        //数据后备区长度,差分升级时,再分为28K + 96K,其中28K为差分数据区,96K为合并后数据区
+#define FLASH_CFG_SIZE          (4 * 1024)          //配置信息长度
+#endif
+
+#ifdef FLASH_SIZE_512K
+//FLASH分区
+#define FLASH_BOOT_BASE    		(0x08000000)        //bootloader起始地址,32K - 64B
+#define FLASH_APP_BASE    		(0x08007FC0)        //应用程序起始地址,64B + 208KB
+#define FLASH_APP_ENTRY         (0x08008000)        //应用程序入口
+#define FLASH_BAK_BASE    		(0x0803C000)        //数据后备区
+#define FLASH_CFG_BASE          (0x0807F000)        //508K-512K,保存一些重要的配置信息,4K
+
+#define FLASH_BOOT_SIZE			(32 * 1024 - 64)    //bootloader长度
+#define FLASH_APP_SIZE			(208 * 1024 + 64)   //应用程序长度
+#define FLASH_BAK_SIZE			(268 * 1024)        //数据后备区长度,差分升级时,再分为60K + 208K,其中60K为差分数据区,208K为合并后数据区
+#define FLASH_CFG_SIZE          (4 * 1024)          //配置信息长度
+#endif
+
+#ifdef FLASH_SIZE_1024K
+//FLASH分区
+#define FLASH_BOOT_BASE    		(0x80000000)        //bootloader起始地址,32K - 64B
+#define FLASH_APP_BASE    		(0x08007FC0)        //应用程序起始地址,64B + 464KB
+#define FLASH_APP_ENTRY         (0x08008000)        //应用程序入口
+#define FLASH_BAK_BASE    		(0x0807C000)        //数据后备区
+#define FLASH_CFG_BASE          (0x080FF000)        //1020K-1024K,保存一些重要的配置信息,4K
+
+#define FLASH_BOOT_SIZE			(32 * 1024 - 64)    //bootloader长度
+#define FLASH_APP_SIZE			(464 * 1024 + 64)   //应用程序长度
+#define FLASH_BAK_SIZE			(524 * 1024)        //数据后备区长度,差分升级时,再分为60K + 464K,其中60K为差分数据区,464K为合并后数据区
+#define FLASH_CFG_SIZE          (4 * 1024)          //配置信息长度
+#endif
+
+
+
+/*******************************************************************************************************/
+typedef enum
+{
+    flash_boot,
+    flash_app,
+    flash_bak,
+    flash_cfg
+} flash_partition_enum;
+
+/*******************************************************************************************************/
+int flash_partition_addr(flash_partition_enum part, uint32_t *addr);
+uint32_t flash_partition_size(flash_partition_enum part);
+int flash_partition_erase(flash_partition_enum part, uint32_t addr, uint32_t size);
+int flash_write_without_erase(flash_partition_enum part, uint32_t addr, const void *p, uint32_t len);
+int flash_write(flash_partition_enum part, uint32_t addr, const void *p, uint32_t len);
+int flash_read(flash_partition_enum part, uint32_t addr, void *p, uint32_t len);
+uint8_t* flash_read_fp(flash_partition_enum part, uint32_t addr);
+uint32_t flash_sum(uint32_t addr, uint32_t len);
+uint32_t flash_crc(uint32_t addr, uint32_t len);
+uint32_t flash_partition_crc(flash_partition_enum part, uint32_t addr, uint32_t len);
+
+#endif
+/*******************************************************************************************************
+**                            End Of File
+********************************************************************************************************/

+ 87 - 0
src/master/user/app/vFile.c

@@ -0,0 +1,87 @@
+/**
+  ******************************************************************************
+  * @file    vFile.c
+  * @author  eming
+  * @version V1.0.0
+  * @date    2022-03-21
+  * @brief   虚拟文件接口,将保存在内部Flash的数据虚拟为文件
+  ******************************************************************************
+  */
+  
+#include <stdlib.h>
+#include <string.h>
+#include "vFile.h"
+
+vFile *vfopen(const uint8_t *dp, uint32_t size)
+{
+    vFile *fp = NULL;
+    
+    fp = malloc(sizeof(vFile));
+    if(fp != NULL)
+    {
+        fp->curptr = (uint8_t*)dp;
+        fp->offset = 0;
+        fp->size = size;
+    }
+    
+    return(fp);
+}
+
+int vfread(vFile *fp, uint8_t *buff, int len)
+{
+    if(fp != NULL)
+    {
+        if((fp->offset + len) > fp->size)
+        {
+            len = fp->size - fp->offset;
+        }
+        memcpy(buff, fp->curptr + fp->offset, len);
+        fp->offset += len;
+        
+        return(len);
+    }
+    
+    return(0);
+}
+
+uint8_t *vfgetpos(vFile *fp, uint32_t *position)
+{
+    if(fp != NULL)
+    {
+        *position = fp->offset;
+        
+        return(fp->curptr + fp->offset);
+    }
+    
+    return(NULL);
+}
+
+int vfsetpos(vFile *fp, uint32_t position)
+{
+    if(fp != NULL)
+    {
+        fp->offset = position;
+    }
+    
+    return(fp->offset);
+}
+
+int vfclose(vFile *fp)
+{
+    if(fp != NULL)
+    {
+        free(fp);
+    }
+    
+    return(0);
+}
+
+uint32_t vfgetlen(vFile *fp)
+{
+    return(fp->size);
+}
+
+/*******************************************************************************************************
+**                            End Of File
+********************************************************************************************************/
+

+ 24 - 0
src/master/user/app/vFile.h

@@ -0,0 +1,24 @@
+#ifndef __VFILE_H__
+#define __VFILE_H__
+/*******************************************************************************************************/
+#include "stdint.h"
+
+typedef struct
+{
+    uint8_t *curptr;
+    uint32_t offset;
+    uint32_t size;
+}vFile;
+
+/*******************************************************************************************************/
+vFile *vfopen(const uint8_t *dp, uint32_t size);
+int vfread(vFile *fp, uint8_t *buff, int len);
+uint8_t *vfgetpos(vFile *fp, uint32_t *position);
+int vfsetpos(vFile *fp, uint32_t position);
+int vfclose(vFile *fp);
+uint32_t vfgetlen(vFile *fp);
+
+#endif
+/*******************************************************************************************************
+**                            End Of File
+********************************************************************************************************/

+ 360 - 0
src/master/user/app/ymodem.c

@@ -0,0 +1,360 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "usr_cfg.h"
+#include "uart.h"
+#include "ota_flash.h"
+// #include "shell.h"
+// #include "shell_port.h"
+#include "ymodem.h"
+#include "iap.h"
+// #include "sys_rst.h"
+
+#if CONFIG_YMODEM_ENABLE
+
+// #define	YMODEM_PORT_USE         (UART1_em)
+// //接口
+// #define ymodem_data_read(a,b)   uart_ReadData(YMODEM_PORT_USE,a,b)
+// #define ymodem_data_write(a,b)  uart_WriteData(YMODEM_PORT_USE,a,b)
+// #define ymodem_data_len()       uart_GetRcvDataNum(YMODEM_PORT_USE)
+// #define ymodem_data_clear()     uart_buffer_clear(YMODEM_PORT_USE)
+
+#define	YMODEM_PORT_USE         (0)
+//接口
+#define ymodem_data_read(a,b)   11//uart_ReadData(YMODEM_PORT_USE,a,b)
+#define ymodem_data_write(a,b)  11//uart_WriteData(YMODEM_PORT_USE,a,b)
+#define ymodem_data_len()       11//uart_GetRcvDataNum(YMODEM_PORT_USE)
+#define ymodem_data_clear()     //uart_buffer_clear(YMODEM_PORT_USE)
+
+//其他宏
+#define ymodem_tmout_en() 		{ymodem_buff.tmout_cunt = 0;ymodem_buff.tmout_t = TRUE;}
+#define ymodem_tmout_dis() 		{ymodem_buff.tmout_cunt = 0;ymodem_buff.tmout_t = FALSE;}
+
+static ymodem_buff_stk			ymodem_buff;
+static ymodem_context_stk       ymodem_context = {0};
+
+/**
+ * @brief 通信超时
+ * @details 1S内没接收到新数据,抛弃前面接收的数据
+ *
+ * @param 无
+ * @return 无
+ *   @retval 略
+ */
+void ymodem_timer(void)
+{
+    if(ymodem_buff.tmout_t == TRUE)
+    {
+        ymodem_buff.tmout_cunt++;
+        if(ymodem_buff.tmout_cunt > 100)
+        {
+            ymodem_buff.tmout_cunt = 0;
+            ymodem_buff.tmout_t = FALSE;
+            ymodem_buff.num = 0;
+        }
+    }
+}
+
+/**
+ * @brief 通信数据发送
+ * @details 1S内没接收到新数据,抛弃前面接收的数据
+ *
+ * @param p,待发送的数据指针
+ * @param len,待发送的数据长度
+ * @return 无
+ *   @retval 略
+ */
+static void ymodem_send_data(uint8 dat)
+{
+    ymodem_data_clear();
+    ymodem_data_write(&dat, 1);
+    ymodem_context.comm_tmout = 0;
+}
+
+/**
+ * @brief   计算接收到包的 CRC-16.
+ * @param   *data:  要计算的数据的数组.
+ * @param   length: 数据的大小,128字节或1024字节.
+ * @return  status: 计算CRC.
+ */
+static uint16_t ymodem_calc_crc(uint8 *data, uint16 length)
+{
+    uint16 crc = 0u;
+    while (length)
+    {
+        length--;
+        crc = crc ^ ((uint16) * data++ << 8u);
+        for (uint8 i = 0; i < 8; i++)
+        {
+            if (crc & 0x8000u)
+            {
+                crc = (crc << 1) ^ 0x1021;
+            }
+            else
+            {
+                crc = crc << 1;
+            }
+        }
+    }
+    return crc;
+}
+
+/**
+ * @brief 接收数据处理函数
+ * @details 
+ *
+ * @param p,数据指针
+ * @param len,数据长度
+ * @return 无
+ *   @retval 略
+ */
+static void ymodem_data_handler(uint8 *p, uint16 len)
+{
+    uint16 dat_len, crc, str_len;
+    ymodem_frame_stk *stkp;
+    
+    stkp = (ymodem_frame_stk*)p;
+
+    switch(stkp->stk.h1)
+    {
+    case YMODEM_SOH:
+    case YMODEM_STX:
+        if(stkp->stk.h1 == YMODEM_SOH)
+        {
+            dat_len = YMODEM_PACKET_128_SIZE;
+        }
+        else
+        {
+            dat_len = YMODEM_PACKET_1024_SIZE;
+        }
+        //CRC校验
+        crc = (stkp->stk.dat[dat_len] << 8) + stkp->stk.dat[dat_len + 1];
+        if(crc != ymodem_calc_crc(stkp->stk.dat, dat_len))return;
+        
+        //包处理
+        if(ymodem_context.pkgs_num == 0)
+        {
+            //第一个包,提取文件信息
+            str_len = strlen((char*)stkp->stk.dat);
+            ymodem_context.file_size = atoi((char*)&stkp->stk.dat[str_len + 1]);
+        }
+        else
+        {
+            // //写入数据
+            // if(ymodem_context.file_offset < ymodem_context.file_size)
+            // {
+            //     flash_write_without_erase(ymodem_context.flash_partition, ymodem_context.file_offset, stkp->stk.dat, dat_len);
+            //     ymodem_context.file_offset += dat_len;
+            // }
+            // else
+            // {
+            //     //空包
+                
+            // }
+        }
+        ymodem_context.pkgs_num++;
+        //发送应答
+        ymodem_send_data(YMODEM_ACK);        
+        break;
+    
+    case YMODEM_EOT:
+        if(ymodem_context.eot_num == 0)
+        {
+            ymodem_context.eot_num++;
+            ymodem_send_data(YMODEM_NAK); 
+        }
+        else
+        {
+            ymodem_send_data(YMODEM_ACK);
+            // //接收完成
+            // if(ymodem_context.flash_partition == flash_bak)
+            // {
+            //     iap_upgrade_start();
+            // }
+            // reboot();
+            
+            //恢复寄存器
+            ymodem_context.task_ps = 1;
+            ymodem_context.pkgs_num = 0;
+            ymodem_context.eot_num = 0;
+            ymodem_context.file_offset = 0;
+        }
+        break;
+    }
+}
+    
+/**
+ * @brief 取帧函数
+ * @details 从数据流中提取符合特征的数据帧
+ *
+ * @param 无
+ * @return 无
+ *   @retval 略
+ */
+static void ymodem_frame(uint8 dat)
+{
+    switch(ymodem_buff.num)
+    {
+    case 0:								//判断帧头
+        if((YMODEM_SOH == dat) || (YMODEM_STX == dat))
+        {
+            ymodem_buff.buff[ymodem_buff.num++] = dat;
+            ymodem_tmout_en();
+        }
+        else if(YMODEM_EOT == dat)
+        {
+            ymodem_buff.buff[ymodem_buff.num++] = dat;
+            ymodem_data_handler(ymodem_buff.buff, 1);
+            ymodem_buff.num = 0;
+            ymodem_tmout_dis();	
+        }
+        else
+        {
+            ymodem_buff.num = 0;
+            ymodem_tmout_dis();	
+        }
+        break;
+
+    case 1:
+        ymodem_buff.buff[ymodem_buff.num++] = dat;
+        ymodem_tmout_en();
+        break;
+
+    case 2:
+        if(((dat + ymodem_buff.buff[1]) & 0xFF) == 0xFF)
+        {
+            ymodem_buff.buff[ymodem_buff.num++] = dat;
+            ymodem_tmout_en();
+            if(ymodem_buff.buff[0] == YMODEM_SOH)
+            {
+                ymodem_buff.len = YMODEM_PACKET_128_SIZE + 5;
+            }
+            else
+            {
+                ymodem_buff.len = YMODEM_PACKET_1024_SIZE + 5;
+            }
+        }
+        else
+        {
+            ymodem_buff.num = 0;
+            ymodem_tmout_dis();
+        }
+        break;
+
+    default:
+        if(ymodem_buff.num < ymodem_buff.len)
+        {
+            ymodem_buff.buff[ymodem_buff.num++] = dat;
+            ymodem_tmout_en();
+            if(ymodem_buff.num == ymodem_buff.len)
+            {
+                ymodem_data_handler(ymodem_buff.buff,ymodem_buff.len);
+                ymodem_buff.num = 0;
+                ymodem_tmout_dis();
+            }			
+        }
+        else
+        {
+            ymodem_buff.num = 0;
+            ymodem_tmout_dis();
+        }
+        break;
+    }
+}
+
+/**
+ * @brief   ymodem主函数.
+ * @param   void.
+ * @return  void.
+ */
+void ymodem_task(void)
+{
+    uint16 len;
+    uint8 buff[32];
+    
+    //接收数据处理
+    if(ymodem_context.task_ps > 0)
+    {
+        //超时定时器
+        ymodem_timer();
+        //接收数据处理
+        if(ymodem_data_len() > 0)
+        {
+            //读取数据
+            len = ymodem_data_read(buff, sizeof(buff));
+            for(int i = 0; i < len; i++)
+            {
+                ymodem_frame(buff[i]);
+            }
+        }        
+    }
+    
+    //任务流程控制
+    switch(ymodem_context.task_ps)
+    {
+    case 0:
+    default:
+        break;
+    
+    case 1:
+        ymodem_send_data(YMODEM_C);
+        ymodem_context.comm_tmout = 0;
+        ymodem_context.task_ps = 2;
+        break;
+    
+    case 2:
+        //接收帧超时
+        ymodem_context.comm_tmout++;
+        if(ymodem_context.comm_tmout > 100)
+        {
+            ymodem_context.task_ps = 1;
+        }
+        break;
+
+    }
+}
+
+#if CONFIG_SHELL_ENABLE
+/**
+ * @brief   ymodem开始.
+ * @param   void.
+ * @return  void.
+ */
+void ymodem_start(void *arg)
+{
+    static const char tips[] = "ymodem [app, patch]\r\n";
+    char *argv[2];
+    uint32_t entry;
+    // int argc = cmdline_strtok((char *)arg, argv, 2);
+    
+    // if(argc < 2)
+    // {
+    //     printl((char *)tips, sizeof(tips) - 1);
+    //     return;
+    // }
+    
+    // if(strcmp(argv[1], "app") == 0)
+    // {
+    //     ymodem_context.flash_partition = flash_app;
+    //     flash_partition_erase(flash_app, 0, FLASH_APP_SIZE);
+    // }
+    // else if(strcmp(argv[1], "patch") == 0)
+    // {
+    //     ymodem_context.flash_partition = flash_bak;
+    //     flash_partition_erase(flash_bak, 0, FLASH_BAK_SIZE);
+    // }
+    // ymodem_context.task_ps = 1;
+    // ymodem_context.pkgs_num = 0;
+    // ymodem_context.eot_num = 0;
+    // ymodem_context.file_offset = 0;
+    // shell_port_enable(FALSE);
+}
+#endif
+
+#else
+void ymodem_task(void) {}
+#endif
+/*******************************************************************************************************
+**                            End Of File
+********************************************************************************************************/
+

+ 67 - 0
src/master/user/app/ymodem.h

@@ -0,0 +1,67 @@
+#ifndef __YMODEM_H__
+#define __YMODEM_H__
+/*******************************************************************************************************/
+#include "type.h"
+
+#define YMODEM_BUFF_LEN             (3 + 1024 + 2 + 1)
+
+/* 数据包大小. */
+#define YMODEM_PACKET_128_SIZE      (128)
+#define YMODEM_PACKET_1024_SIZE     (1024)
+#define YMODEM_PACKET_CRC_SIZE      (2)
+
+/* 协议定义的字节. */
+#define YMODEM_SOH                  (1)     /**< 包头 (128 bytes). */
+#define YMODEM_STX                  (2)     /**< 包头 (1024 bytes). */
+#define YMODEM_EOT                  (4)     /**< 传输结束. */
+#define YMODEM_ACK                  (6)     /**< 应答. */
+#define YMODEM_NAK                  (0x15)  /**< 非应答. */
+#define YMODEM_CAN                  (0x18)  /**< 取消. */
+#define YMODEM_C                    (0x43)  /**< ASCII“C”,要通知上位机,我们要用CRC16. */
+
+/*******************************************************************************************************/
+//接收缓冲区
+typedef struct
+{
+  uint8   buff[YMODEM_BUFF_LEN];
+  uint16  num;					  //数据计数器
+  uint16  len;				   	//数据包长度
+  uint8	  tmout_cunt;
+  uint8	  tmout_t;
+} ymodem_buff_stk;
+
+//数据帧格式定义
+typedef union
+{
+ uint8 array[YMODEM_BUFF_LEN];
+ struct
+ { 
+    uint8 h1;
+    uint8 sn;
+    uint8 sn_c;
+    uint8 dat[1];
+    uint8 crc_h;
+    uint8 crc_l;
+ }stk;
+}ymodem_frame_stk;
+
+//传输上下文
+typedef struct
+{
+   uint8  task_ps;
+   uint8  comm_tmout; 
+   uint8  eot_num;
+   uint16 pkgs_num;
+   int    flash_partition;
+   uint32 file_size;
+   uint32 file_offset;
+}ymodem_context_stk;
+
+/*******************************************************************************************************/
+void ymodem_start(void *arg);
+void ymodem_task(void);
+
+#endif
+/*******************************************************************************************************
+**                            End Of File
+********************************************************************************************************/

+ 66 - 0
src/master/user/db/db.c

@@ -0,0 +1,66 @@
+/*
+ * @Description: 
+ * @Version: 2.0
+ * @Author: Seven
+ * @Date: 2023-11-08 16:20:03
+ * @LastEditors: Seven
+ * @LastEditTime: 2023-11-13 14:34:33
+ */
+#include "stdint.h"
+#include "ustdio.h"
+#include "string.h"
+#include "ota_flash.h"
+#include "iap.h"
+#include "mylib.h"
+#include "db.h"
+#include "stdbool.h"
+
+/********************************************************************************************************/
+// #define flash_mem_write(addr, buff, cunt)       flash_write(flash_cfg, addr, buff,cunt)
+// #define flash_mem_read(addr, buff, cunt)        flash_read(flash_cfg, addr, buff,cunt)
+
+//Êý¾ÝÊ×µØÖ·ºÍÊý¾Ý³¤¶È
+const uint32_t DB_INFO[][2] = 
+{ 
+    {DB_APPBAK_ADDR,        sizeof(IAP_AppBak_stk)},      \
+
+};
+
+int db_read(void *datp, DB_TYPE type)
+{
+    uint32_t addr;
+    uint32_t len;
+    bool   err;
+
+    addr = DB_INFO[type][0];
+    len  = DB_INFO[type][1];
+
+    // err = flash_mem_read(addr, datp, len);
+
+    if(FALSE == err)
+    {
+        memset(datp, 0, len);
+        return(FALSE);
+    }
+    return(TRUE);
+}
+
+void db_write(const void *datp, DB_TYPE type)
+{
+    uint32_t addr;
+    uint32_t len;
+
+    addr = DB_INFO[type][0];
+    len  = DB_INFO[type][1];
+
+    // flash_mem_write(addr, datp, len);
+}
+
+void db_init(void)
+{
+
+}
+
+/*******************************************************************************************************
+**                            End Of File
+********************************************************************************************************/

+ 26 - 0
src/master/user/db/db.h

@@ -0,0 +1,26 @@
+#ifndef __DB_H__
+#define __DB_H__
+/*******************************************************************************************************/
+//数据地址定义,尽量按照EEPROM页对齐
+#define DB_CFG_BASE         (0)
+
+#define DB_APPBAK_ADDR      (DB_CFG_BASE)          //程序升级标志,1字节 
+
+
+//==========================================================================
+//数据类型枚举
+typedef enum
+{
+    DB_APPBAK = 0,
+    
+} DB_TYPE;
+/*******************************************************************************************************/
+#include "stdint.h"
+
+extern int  db_read(void *datp, DB_TYPE type);
+extern void db_write(const void *datp, DB_TYPE type);
+
+#endif
+/*******************************************************************************************************
+**                            End Of File
+********************************************************************************************************/

+ 285 - 0
src/master/user/inc/BIN.H

@@ -0,0 +1,285 @@
+/*————————————————————
+〖说明〗这是直接输入二进制常数的KEIL C补丁,如输入B0000_0101;
+则宏替换后就是0x05;在做某些位操作时这个补丁会带来很大的方便。
+由于是用#define定义的,所以程序中包含这个头文件,并不会增加代码长度。
+〖文件〗BIN.H ﹫2001/03/23
+〖作者〗龙啸九天 c51@yeah.net http://mcs51.yeah.net
+〖修改〗修改建议请到论坛公布 http://c51bbs.yeah.net
+〖版本〗V1.00A Build 0323
+—————————————————————*/
+#ifndef __BIN_H__
+#define __BIN_H__
+
+#define B0000_0000 0x00
+#define B0000_0001 0x01
+#define B0000_0010 0x02
+#define B0000_0011 0x03
+#define B0000_0100 0x04
+#define B0000_0101 0x05
+#define B0000_0110 0x06
+#define B0000_0111 0x07
+#define B0000_1000 0x08
+#define B0000_1001 0x09
+#define B0000_1010 0x0A
+#define B0000_1011 0x0B
+#define B0000_1100 0x0C
+#define B0000_1101 0x0D
+#define B0000_1110 0x0E
+#define B0000_1111 0x0F
+
+#define B0001_0000 0x10
+#define B0001_0001 0x11
+#define B0001_0010 0x12
+#define B0001_0011 0x13
+#define B0001_0100 0x14
+#define B0001_0101 0x15
+#define B0001_0110 0x16
+#define B0001_0111 0x17
+#define B0001_1000 0x18
+#define B0001_1001 0x19
+#define B0001_1010 0x1A
+#define B0001_1011 0x1B
+#define B0001_1100 0x1C
+#define B0001_1101 0x1D
+#define B0001_1110 0x1E
+#define B0001_1111 0x1F
+
+#define B0010_0000 0x20
+#define B0010_0001 0x21
+#define B0010_0010 0x22
+#define B0010_0011 0x23
+#define B0010_0100 0x24
+#define B0010_0101 0x25
+#define B0010_0110 0x26
+#define B0010_0111 0x27
+#define B0010_1000 0x28
+#define B0010_1001 0x29
+#define B0010_1010 0x2A
+#define B0010_1011 0x2B
+#define B0010_1100 0x2C
+#define B0010_1101 0x2D
+#define B0010_1110 0x2E
+#define B0010_1111 0x2F
+
+#define B0011_0000 0x30
+#define B0011_0001 0x31
+#define B0011_0010 0x32
+#define B0011_0011 0x33
+#define B0011_0100 0x34
+#define B0011_0101 0x35
+#define B0011_0110 0x36
+#define B0011_0111 0x37
+#define B0011_1000 0x38
+#define B0011_1001 0x39
+#define B0011_1010 0x3A
+#define B0011_1011 0x3B
+#define B0011_1100 0x3C
+#define B0011_1101 0x3D
+#define B0011_1110 0x3E
+#define B0011_1111 0x3F
+
+#define B0100_0000 0x40
+#define B0100_0001 0x41
+#define B0100_0010 0x42
+#define B0100_0011 0x43
+#define B0100_0100 0x44
+#define B0100_0101 0x45
+#define B0100_0110 0x46
+#define B0100_0111 0x47
+#define B0100_1000 0x48
+#define B0100_1001 0x49
+#define B0100_1010 0x4A
+#define B0100_1011 0x4B
+#define B0100_1100 0x4C
+#define B0100_1101 0x4D
+#define B0100_1110 0x4E
+#define B0100_1111 0x4F
+
+#define B0101_0000 0x50
+#define B0101_0001 0x51
+#define B0101_0010 0x52
+#define B0101_0011 0x53
+#define B0101_0100 0x54
+#define B0101_0101 0x55
+#define B0101_0110 0x56
+#define B0101_0111 0x57
+#define B0101_1000 0x58
+#define B0101_1001 0x59
+#define B0101_1010 0x5A
+#define B0101_1011 0x5B
+#define B0101_1100 0x5C
+#define B0101_1101 0x5D
+#define B0101_1110 0x5E
+#define B0101_1111 0x5F
+
+#define B0110_0000 0x60
+#define B0110_0001 0x61
+#define B0110_0010 0x62
+#define B0110_0011 0x63
+#define B0110_0100 0x64
+#define B0110_0101 0x65
+#define B0110_0110 0x66
+#define B0110_0111 0x67
+#define B0110_1000 0x68
+#define B0110_1001 0x69
+#define B0110_1010 0x6A
+#define B0110_1011 0x6B
+#define B0110_1100 0x6C
+#define B0110_1101 0x6D
+#define B0110_1110 0x6E
+#define B0110_1111 0x6F
+
+#define B0111_0000 0x70
+#define B0111_0001 0x71
+#define B0111_0010 0x72
+#define B0111_0011 0x73
+#define B0111_0100 0x74
+#define B0111_0101 0x75
+#define B0111_0110 0x76
+#define B0111_0111 0x77
+#define B0111_1000 0x78
+#define B0111_1001 0x79
+#define B0111_1010 0x7A
+#define B0111_1011 0x7B
+#define B0111_1100 0x7C
+#define B0111_1101 0x7D
+#define B0111_1110 0x7E
+#define B0111_1111 0x7F
+
+#define B1000_0000 0x80
+#define B1000_0001 0x81
+#define B1000_0010 0x82
+#define B1000_0011 0x83
+#define B1000_0100 0x84
+#define B1000_0101 0x85
+#define B1000_0110 0x86
+#define B1000_0111 0x87
+#define B1000_1000 0x88
+#define B1000_1001 0x89
+#define B1000_1010 0x8A
+#define B1000_1011 0x8B
+#define B1000_1100 0x8C
+#define B1000_1101 0x8D
+#define B1000_1110 0x8E
+#define B1000_1111 0x8F
+
+#define B1001_0000 0x90
+#define B1001_0001 0x91
+#define B1001_0010 0x92
+#define B1001_0011 0x93
+#define B1001_0100 0x94
+#define B1001_0101 0x95
+#define B1001_0110 0x96
+#define B1001_0111 0x97
+#define B1001_1000 0x98
+#define B1001_1001 0x99
+#define B1001_1010 0x9A
+#define B1001_1011 0x9B
+#define B1001_1100 0x9C
+#define B1001_1101 0x9D
+#define B1001_1110 0x9E
+#define B1001_1111 0x9F
+
+#define B1010_0000 0xA0
+#define B1010_0001 0xA1
+#define B1010_0010 0xA2
+#define B1010_0011 0xA3
+#define B1010_0100 0xA4
+#define B1010_0101 0xA5
+#define B1010_0110 0xA6
+#define B1010_0111 0xA7
+#define B1010_1000 0xA8
+#define B1010_1001 0xA9
+#define B1010_1010 0xAA
+#define B1010_1011 0xAB
+#define B1010_1100 0xAC
+#define B1010_1101 0xAD
+#define B1010_1110 0xAE
+#define B1010_1111 0xAF
+
+#define B1011_0000 0xB0
+#define B1011_0001 0xB1
+#define B1011_0010 0xB2
+#define B1011_0011 0xB3
+#define B1011_0100 0xB4
+#define B1011_0101 0xB5
+#define B1011_0110 0xB6
+#define B1011_0111 0xB7
+#define B1011_1000 0xB8
+#define B1011_1001 0xB9
+#define B1011_1010 0xBA
+#define B1011_1011 0xBB
+#define B1011_1100 0xBC
+#define B1011_1101 0xBD
+#define B1011_1110 0xBE
+#define B1011_1111 0xBF
+
+#define B1100_0000 0xC0
+#define B1100_0001 0xC1
+#define B1100_0010 0xC2
+#define B1100_0011 0xC3
+#define B1100_0100 0xC4
+#define B1100_0101 0xC5
+#define B1100_0110 0xC6
+#define B1100_0111 0xC7
+#define B1100_1000 0xC8
+#define B1100_1001 0xC9
+#define B1100_1010 0xCA
+#define B1100_1011 0xCB
+#define B1100_1100 0xCC
+#define B1100_1101 0xCD
+#define B1100_1110 0xCE
+#define B1100_1111 0xCF
+
+#define B1101_0000 0xD0
+#define B1101_0001 0xD1
+#define B1101_0010 0xD2
+#define B1101_0011 0xD3
+#define B1101_0100 0xD4
+#define B1101_0101 0xD5
+#define B1101_0110 0xD6
+#define B1101_0111 0xD7
+#define B1101_1000 0xD8
+#define B1101_1001 0xD9
+#define B1101_1010 0xDA
+#define B1101_1011 0xDB
+#define B1101_1100 0xDC
+#define B1101_1101 0xDD
+#define B1101_1110 0xDE
+#define B1101_1111 0xDF
+
+#define B1110_0000 0xE0
+#define B1110_0001 0xE1
+#define B1110_0010 0xE2
+#define B1110_0011 0xE3
+#define B1110_0100 0xE4
+#define B1110_0101 0xE5
+#define B1110_0110 0xE6
+#define B1110_0111 0xE7
+#define B1110_1000 0xE8
+#define B1110_1001 0xE9
+#define B1110_1010 0xEA
+#define B1110_1011 0xEB
+#define B1110_1100 0xEC
+#define B1110_1101 0xED
+#define B1110_1110 0xEE
+#define B1110_1111 0xEF
+
+#define B1111_0000 0xF0
+#define B1111_0001 0xF1
+#define B1111_0010 0xF2
+#define B1111_0011 0xF3
+#define B1111_0100 0xF4
+#define B1111_0101 0xF5
+#define B1111_0110 0xF6
+#define B1111_0111 0xF7
+#define B1111_1000 0xF8
+#define B1111_1001 0xF9
+#define B1111_1010 0xFA
+#define B1111_1011 0xFB
+#define B1111_1100 0xFC
+#define B1111_1101 0xFD
+#define B1111_1110 0xFE
+#define B1111_1111 0xFF 
+
+#endif

+ 77 - 0
src/master/user/inc/stm32f10x_conf.h

@@ -0,0 +1,77 @@
+/**
+  ******************************************************************************
+  * @file    Project/STM32F10x_StdPeriph_Template/stm32f10x_conf.h
+  * @author  MCD Application Team
+  * @version V3.5.0
+  * @date    08-April-2011
+  * @brief   Library configuration file.
+  ******************************************************************************
+  * @attention
+  *
+  * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
+  * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
+  * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
+  * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
+  * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
+  * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
+  *
+  * <h2><center>&copy; COPYRIGHT 2011 STMicroelectronics</center></h2>
+  ******************************************************************************
+  */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __STM32F10x_CONF_H
+#define __STM32F10x_CONF_H
+
+/* Includes ------------------------------------------------------------------*/
+/* Uncomment/Comment the line below to enable/disable peripheral header file inclusion */
+#include "stm32f10x_adc.h"
+#include "stm32f10x_bkp.h"
+#include "stm32f10x_can.h"
+#include "stm32f10x_cec.h"
+#include "stm32f10x_crc.h"
+#include "stm32f10x_dac.h"
+#include "stm32f10x_dbgmcu.h"
+#include "stm32f10x_dma.h"
+#include "stm32f10x_exti.h"
+#include "stm32f10x_flash.h"
+#include "stm32f10x_fsmc.h"
+#include "stm32f10x_gpio.h"
+#include "stm32f10x_i2c.h"
+#include "stm32f10x_iwdg.h"
+#include "stm32f10x_pwr.h"
+#include "stm32f10x_rcc.h"
+#include "stm32f10x_rtc.h"
+#include "stm32f10x_sdio.h"
+#include "stm32f10x_spi.h"
+#include "stm32f10x_tim.h"
+#include "stm32f10x_usart.h"
+#include "stm32f10x_wwdg.h"
+#include "misc.h" /* High level functions for NVIC and SysTick (add-on to CMSIS functions) */
+
+/* Exported types ------------------------------------------------------------*/
+/* Exported constants --------------------------------------------------------*/
+/* Uncomment the line below to expanse the "assert_param" macro in the
+   Standard Peripheral Library drivers code */
+#define USE_FULL_ASSERT    1
+
+/* Exported macro ------------------------------------------------------------*/
+#ifdef  USE_FULL_ASSERT
+
+/**
+  * @brief  The assert_param macro is used for function's parameters check.
+  * @param  expr: If expr is false, it calls assert_failed function which reports
+  *         the name of the source file and the source line number of the call
+  *         that failed. If expr is true, it returns no value.
+  * @retval None
+  */
+#define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__))
+/* Exported functions ------------------------------------------------------- */
+void assert_failed(uint8_t *file, uint32_t line);
+#else
+#define assert_param(expr) ((void)0)
+#endif /* USE_FULL_ASSERT */
+
+#endif /* __STM32F10x_CONF_H */
+
+/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/

+ 54 - 0
src/master/user/inc/stm32f10x_it.h

@@ -0,0 +1,54 @@
+/**
+  ******************************************************************************
+  * @file    Project/STM32F10x_StdPeriph_Template/stm32f10x_it.h
+  * @author  MCD Application Team
+  * @version V3.5.0
+  * @date    08-April-2011
+  * @brief   This file contains the headers of the interrupt handlers.
+  ******************************************************************************
+  * @attention
+  *
+  * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
+  * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
+  * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
+  * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
+  * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
+  * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
+  *
+  * <h2><center>&copy; COPYRIGHT 2011 STMicroelectronics</center></h2>
+  ******************************************************************************
+  */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __STM32F10x_IT_H
+#define __STM32F10x_IT_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32f10x.h"
+
+/* Exported types ------------------------------------------------------------*/
+/* Exported constants --------------------------------------------------------*/
+/* Exported macro ------------------------------------------------------------*/
+/* Exported functions ------------------------------------------------------- */
+
+void NMI_Handler(void);
+void HardFault_Handler(void);
+void MemManage_Handler(void);
+void BusFault_Handler(void);
+void UsageFault_Handler(void);
+void SVC_Handler(void);
+void DebugMon_Handler(void);
+void PendSV_Handler(void);
+void SysTick_Handler(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __STM32F10x_IT_H */
+
+/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/

+ 78 - 0
src/master/user/inc/type.h

@@ -0,0 +1,78 @@
+/*
+ * @Description: 
+ * @Version: 2.0
+ * @Author: Seven
+ * @Date: 2023-11-08 16:20:03
+ * @LastEditors: Seven
+ * @LastEditTime: 2023-11-09 10:57:37
+ */
+#ifndef __TYPE_H__
+#define __TYPE_H__
+/********************************************************************************************************/
+#ifndef TRUE
+#define TRUE  1
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#ifndef ERROR
+#define ERROR 0xFF
+#endif
+
+// typedef unsigned char       bool;
+typedef unsigned char       uint8;	    /* defined for unsigned 8-bits integer variable 	无符号8位整型变量  */
+typedef signed   char       int8;       /* defined for signed 8-bits integer variable		有符号8位整型变量  */
+typedef unsigned short      uint16;	    /* defined for unsigned 16-bits integer variable 	无符号16位整型变量 */
+typedef signed   short      int16; 	    /* defined for signed 16-bits integer variable 		有符号16位整型变量 */
+typedef unsigned long       uint32;     /* defined for unsigned 32-bits integer variable 	无符号32位整型变量 */
+typedef signed   long       int32; 	    /* defined for signed 32-bits integer variable 		有符号32位整型变量 */
+typedef float               fp32;  	    /* single precision floating point variable (32bits)单精度浮点数(32位长度) */
+typedef unsigned long long  uint64;     /* defined for unsigned 64-bits integer variable 	无符号64位整型变量 */
+typedef signed   long long  int64; 	    /* defined for signed 64-bits integer variable 		有符号64位整型变量 */
+typedef double              fp64;       /* double precision floating point variable (64bits)双精度浮点数(64位长度) */
+/********************************************************************************************************/
+#define BigtoLittle16(x)    ((((uint16)(x) & 0xff00) >> 8) | (((uint16)(x) & 0x00ff) << 8))
+#define BigtoLittle32(x)    ((((uint32)(x) & 0xff000000) >> 24) | \
+                            (((uint32)(x) & 0x00ff0000) >> 8) | \
+                            (((uint32)(x) & 0x0000ff00) << 8) | \
+                            (((uint32)(x) & 0x000000ff) << 24))
+/********************************************************************************************************/
+//定义一个联合,将一个64位数分拆成4个8位数,以便于计算
+//M3内核为小端方式,即低字节在低位,高字节在高位
+typedef union
+{
+    uint64 d64;
+    uint8  d8[8];
+} U64_U8;
+//定义一个联合,将一个64位数分拆成4个8位数,以便于计算
+//M3内核为小端方式,即低字节在低位,高字节在高位
+typedef union
+{
+    fp64   f64;
+    uint8  d8[8];
+} F64_U8;
+//定义一个联合,将一个32位数分拆成4个8位数,以便于计算
+//M3内核为小端方式,即低字节在低位,高字节在高位
+typedef union
+{
+    uint32 d32;
+    uint8  d8[4];
+} U32_U8;
+/********************************************************************************************************/
+//定义一个联合,将一个16位数分拆成2个8位数,以便于计算
+typedef union
+{
+    uint16 d16;
+    uint8  d8[2];
+} U16_U8;
+/********************************************************************************************************/
+//定义一个联合,将一个16位数分拆成2个8位数,以便于计算
+typedef union
+{
+    int16  d16;
+    uint8  d8[2];
+} I16_U8;
+/********************************************************************************************************/
+#endif

+ 51 - 0
src/master/user/inc/usr_cfg.h

@@ -0,0 +1,51 @@
+/*******************************************************************************************************
+**--------------File Info-------------------------------------------------------------------------------
+** File name:			usr_cfg.h
+** Last modified Date:  2009-04-23
+** Last Version:		1.0
+** Descriptions:		任务函数
+**
+**
+**------------------------------------------------------------------------------------------------------
+** Created by:			Chen Y.M
+** Created date:		2009-04-23
+** Version:				1.0
+** Descriptions:		The original version
+**
+**------------------------------------------------------------------------------------------------------
+** Modified by:
+** Modified date:
+** Version:
+** Descriptions:
+**
+********************************************************************************************************/
+#ifndef __USR_CFG_H
+#define __USR_CFG_H
+
+/*******************************************************************************************************
+** 软硬件版本号
+********************************************************************************************************/
+#define HARD_VER	    "STM32F103VET6"
+#define SOFT_VER	    "1.0.0"
+
+#define BUILD_DATE 		__DATE__
+#define BUILD_TIME 		__TIME__
+
+/*******************************************************************************************************
+** 全局宏定义
+********************************************************************************************************/
+//是否使用SHELL
+#define CONFIG_SHELL_ENABLE     (1)
+
+//是否使用ymodem
+#define CONFIG_YMODEM_ENABLE    (1)
+
+//内部看门狗
+#define CONFIG_WDOG_ENABLE		(0)
+
+
+#endif
+/*******************************************************************************************************
+**                            End Of File
+********************************************************************************************************/
+

+ 89 - 0
src/master/user/lib/crc32.c

@@ -0,0 +1,89 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+#include <stdio.h>
+
+const unsigned int crc32tab[] = 
+{
+    0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL,
+    0x076dc419L, 0x706af48fL, 0xe963a535L, 0x9e6495a3L,
+    0x0edb8832L, 0x79dcb8a4L, 0xe0d5e91eL, 0x97d2d988L,
+    0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, 0x90bf1d91L,
+    0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
+    0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L,
+    0x136c9856L, 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL,
+    0x14015c4fL, 0x63066cd9L, 0xfa0f3d63L, 0x8d080df5L,
+    0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, 0xa2677172L,
+    0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
+    0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L,
+    0x32d86ce3L, 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L,
+    0x26d930acL, 0x51de003aL, 0xc8d75180L, 0xbfd06116L,
+    0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, 0xb8bda50fL,
+    0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
+    0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL,
+    0x76dc4190L, 0x01db7106L, 0x98d220bcL, 0xefd5102aL,
+    0x71b18589L, 0x06b6b51fL, 0x9fbfe4a5L, 0xe8b8d433L,
+    0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, 0xe10e9818L,
+    0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
+    0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL,
+    0x6c0695edL, 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L,
+    0x65b0d9c6L, 0x12b7e950L, 0x8bbeb8eaL, 0xfcb9887cL,
+    0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, 0xfbd44c65L,
+    0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
+    0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL,
+    0x4369e96aL, 0x346ed9fcL, 0xad678846L, 0xda60b8d0L,
+    0x44042d73L, 0x33031de5L, 0xaa0a4c5fL, 0xdd0d7cc9L,
+    0x5005713cL, 0x270241aaL, 0xbe0b1010L, 0xc90c2086L,
+    0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
+    0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L,
+    0x59b33d17L, 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL,
+    0xedb88320L, 0x9abfb3b6L, 0x03b6e20cL, 0x74b1d29aL,
+    0xead54739L, 0x9dd277afL, 0x04db2615L, 0x73dc1683L,
+    0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
+    0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L,
+    0xf00f9344L, 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL,
+    0xf762575dL, 0x806567cbL, 0x196c3671L, 0x6e6b06e7L,
+    0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, 0x67dd4accL,
+    0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
+    0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L,
+    0xd1bb67f1L, 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL,
+    0xd80d2bdaL, 0xaf0a1b4cL, 0x36034af6L, 0x41047a60L,
+    0xdf60efc3L, 0xa867df55L, 0x316e8eefL, 0x4669be79L,
+    0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
+    0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL,
+    0xc5ba3bbeL, 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L,
+    0xc2d7ffa7L, 0xb5d0cf31L, 0x2cd99e8bL, 0x5bdeae1dL,
+    0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, 0x026d930aL,
+    0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
+    0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L,
+    0x92d28e9bL, 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L,
+    0x86d3d2d4L, 0xf1d4e242L, 0x68ddb3f8L, 0x1fda836eL,
+    0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, 0x18b74777L,
+    0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
+    0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L,
+    0xa00ae278L, 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L,
+    0xa7672661L, 0xd06016f7L, 0x4969474dL, 0x3e6e77dbL,
+    0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, 0x37d83bf0L,
+    0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
+    0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L,
+    0xbad03605L, 0xcdd70693L, 0x54de5729L, 0x23d967bfL,
+    0xb3667a2eL, 0xc4614ab8L, 0x5d681b02L, 0x2a6f2b94L,
+    0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, 0x2d02ef8dL 
+};
+ 
+
+unsigned int crc32( const unsigned char *buf, unsigned int size)
+{
+    unsigned int i, crc;
+    crc = 0xFFFFFFFF;
+    
+    for (i = 0; i < size; i++)
+    {
+        crc = crc32tab[(crc ^ buf[i]) & 0xff] ^ (crc >> 8);
+    }
+    return crc ^ 0xFFFFFFFF;
+}
+

+ 9 - 0
src/master/user/lib/crc32.h

@@ -0,0 +1,9 @@
+#ifndef __CRC32_H__
+#define __CRC32_H__
+/*******************************************************************************************************/
+extern unsigned int crc32( const unsigned char *buf, unsigned int size);
+
+#endif
+/*******************************************************************************************************
+**                            End Of File
+********************************************************************************************************/

+ 610 - 0
src/master/user/lib/mylib.c

@@ -0,0 +1,610 @@
+/**
+  ******************************************************************************
+  * @file    mylib.c
+  * @author  eming
+  * @version V1.0.0
+  * @date    2022-03-21
+  * @brief   定义一些公用函数
+  ******************************************************************************
+  */
+#include "stdint.h"
+#include "ustdio.h"
+#include "stdlib.h"
+#include "string.h"
+#include "time.h"
+#include "type.h"
+
+/**
+ * @brief 和校验
+ * @details 字节数组的和校验函数
+ *
+ * @param *p 数组指针
+ * @param size 数组长度
+ * @return 求和结果
+ *   @retval 无
+ */
+uint32_t mylib_sum(const uint8_t *p, uint16_t size)
+{
+    uint32_t sum = 0;
+
+    while(size--)
+    {
+        sum += *(p++);
+    }
+    return(sum);
+}
+
+/**
+ * @brief 数据比较
+ * @details 字节数组的数据比较
+ *
+ * @param *p1 数组1指针
+ * @param *p2 数组2指针
+ * @param size 比较的数据块大小
+ * @return 比较结果
+ *   @retval TRUE 相等
+ *   @retval FALSE 不相等
+ */
+int mylib_memcmp(const void *p1, const void *p2, int size)
+{
+    uint8_t *bp1, *bp2;
+    
+    bp1 = (uint8_t*)p1;
+    bp2 = (uint8_t*)p2;
+    while(size--)
+    {
+        if(*(bp1++) != *(bp2++))return(FALSE);
+    }
+    return(TRUE);
+}
+
+/**
+ * @brief 数据比较
+ * @details 字节数组与指定数据比较
+ *
+ * @param *p1 数组指针
+ * @param value 被比较的数值
+ * @param size 比较的数据块大小
+ * @return 比较结果
+ *   @retval TRUE 相等
+ *   @retval FALSE 不相等
+ */
+int mylib_memcmp_b(uint8_t *p1, uint8_t value, int size)
+{
+    while(size--)
+    {
+        if(*(p1++) != value)return(FALSE);
+    }
+    return(TRUE);
+}
+
+/**
+ * @brief 延时函数
+ * @details 大概为1uS的延时函数
+ *
+ * @param us 需要延时的微秒数
+ * @return 无
+ *   @retval 无
+ */
+void mylib_uDelay(uint32_t us)
+{
+    int i;
+    
+    for(; us > 0; us--)
+    {
+        for(i = 0; i < 40; i++);
+    }
+}
+
+/**
+ * @brief CRC16函数
+ * @details 计算字节数组的CRC16
+ *
+ * @param *p 数组指针
+ * @param size 数组长度
+ * @return 计算结果
+ *   @retval uint16_t CRC16值
+ */
+uint16_t mylib_crc16(uint8_t *p, uint16_t size)
+{
+    uint16_t crc;                        //校验码
+    uint16_t i;
+    uint16_t j;
+    crc = 0xFFFF;
+    for (i = 0; i < size; i++)
+    {
+        crc ^= *p;
+        for (j = 0; j < 8; j++)
+        {
+            if ((crc & 1) == 1)
+            {
+                crc >>= 1;
+                crc ^= 0xA001;
+            }
+            else
+            {
+                crc >>= 1;
+            }
+        }
+        p++;
+    }
+    return(crc);
+}
+
+/**
+ * @brief 16位大小端转换
+ * @details 数据大端小段互相转换函数
+ *
+ * @param *frm 源数组指针
+ * @param *to 目标数组指针
+ * @param size 转换的数据个数(半字)
+ * @return 无
+ *   @retval 无
+ */
+void mylib_BigtoLittle16(const void *frm, void *to, uint16_t size)
+{
+    uint8_t  buff[2];
+    uint8_t 	*fp, *tp;
+
+    fp = (uint8_t *)frm;
+    tp = (uint8_t *)to;
+    while(size--)
+    {
+        buff[0] = fp[0];
+        buff[1] = fp[1];
+        tp[0] 	= buff[1];
+        tp[1] 	= buff[0];
+
+        tp  += 2;
+        fp += 2;
+    }
+}
+
+/**
+ * @brief 32位大小端转换
+ * @details 数据大端小段互相转换函数
+ *
+ * @param *frm 源数组指针
+ * @param *to 目标数组指针
+ * @param size 转换的数据个数(字)
+ * @return 无
+ *   @retval 无
+ */
+void mylib_BigtoLittle32(const void *frm, void *to, uint16_t size)
+{
+    uint8_t buff[4];
+    uint8_t *fp, *tp;
+
+    fp = (uint8_t *)frm;
+    tp = (uint8_t *)to;
+    while(size--)
+    {
+        buff[0] = fp[0];
+        buff[1] = fp[1];
+        buff[2] = fp[2];
+        buff[3] = fp[3];
+        tp[0] 	= buff[3];
+        tp[1] 	= buff[2];
+        tp[2] 	= buff[1];
+        tp[3] 	= buff[0];
+
+        tp  += 4;
+        fp += 4;
+    }
+}
+
+/**
+ * @brief 64位浮点数大小端转换
+ * @details 数据大端小段互相转换函数
+ *
+ * @param dat 浮点数
+ * @return 转换结果
+ *   @retval 转换后的浮点数
+ */
+double mylib_BigtoLittle_fp64(double dat)
+{
+    F64_U8 tmp1, tmp2;
+
+    tmp1.f64 = dat;
+    tmp2.d8[0] = tmp1.d8[7];
+    tmp2.d8[1] = tmp1.d8[6];
+    tmp2.d8[2] = tmp1.d8[5];
+    tmp2.d8[3] = tmp1.d8[4];
+    tmp2.d8[4] = tmp1.d8[3];
+    tmp2.d8[5] = tmp1.d8[2];
+    tmp2.d8[6] = tmp1.d8[1];
+    tmp2.d8[7] = tmp1.d8[0];
+    
+    return(tmp2.f64);
+}
+
+/**
+ * @brief BCD编码函数
+ * @details 二进制数据转BCD码
+ *
+ * @param hex 二进制数据
+ * @return 转换结果
+ *   @retval BCD码
+ */
+uint8_t mylib_HEXtoBCD(uint8_t hex)
+{
+    uint8_t bcd = 0;
+
+    bcd = hex / 10;
+    bcd <<= 4;
+    bcd += hex % 10;
+
+    return(bcd);
+}
+
+/**
+ * @brief BCD解码函数
+ * @details BCD码转二进制数据
+ *
+ * @param bcd BCD码数据
+ * @return 转换结果
+ *   @retval 二进制数据
+ */
+uint8_t mylib_BCDtoHEX(uint8_t bcd)
+{
+    uint8_t hex = 0;
+
+    hex = ((bcd >> 4) & 0x0F) * 10 + (bcd & 0x0F);
+    return(hex);
+}
+
+/**
+ * @brief 数值转字符串
+ * @details 整形数值转字符串
+ *
+ * @param value 整形数值
+ * @param *str 转换结果字符串指针
+ * @param radix 进制
+ * @return 换结果字符串指针
+ */
+char *itoa_(int value, char *str, uint8_t radix)
+{
+    static char szMap[] =
+    {
+        '0', '1', '2', '3', '4', '5',
+        '6', '7', '8', '9', 'a', 'b',
+        'c', 'd', 'e', 'f', 'g', 'h',
+        'i', 'j', 'k', 'l', 'm', 'n',
+        'o', 'p', 'q', 'r', 's', 't',
+        'u', 'v', 'w', 'x', 'y', 'z'
+    };  // 字符映射表
+    int nCount = -1, nIndex;
+    char *pStr = str, nTemp;
+    unsigned int nValue = *(unsigned *)&value;
+
+    if(radix >= 2 && radix <= 36 )          //限制radix必须在2到36之间
+    {
+        if(value < 0 && radix == 10)        //如果是负数就在首位添加负号,并将字符串前移
+        {
+            *pStr++ = '-';
+            value = -value;                 //转为正数,
+        }
+        do                                  //循环转换每一个数字,直到结束
+        {
+            pStr[++nCount] = szMap[nValue % radix];
+            nValue /= radix;
+        }
+        while(nValue > 0);                  //转换结束后字符串是翻的
+        nIndex = (nCount + 1) / 2;          //计算出一半的长度
+        while(nIndex-- > 0)                 //将字符串的字符序翻转
+        {
+            nTemp = pStr[nIndex];
+            pStr[nIndex] = pStr[nCount - nIndex];
+            pStr[nCount - nIndex] = nTemp;
+        }
+    }
+    pStr[nCount + 1] = '\0';                // 置结束符
+    return str;
+}
+
+/**
+ * @brief 数组转字符串
+ * @details 字节数组转字符串
+ *
+ * @param *str 转换后的字符串
+ * @param bytes 被转换的字节数组
+ * @param size 被转换的字节数组长度
+ * @return 转换出的字符串长度
+ */
+int mylib_bytes_to_string(char *str, const uint8_t *bytes, int size)
+{
+    int i;
+
+    char hexArray[] = "0123456789ABCDEF";
+
+    for (i = 0; i < size; i++)
+    {
+        int v = bytes[i] & 0xFF;
+        str[i * 2] = hexArray[v >> 4];
+        str[i * 2 + 1] = hexArray[v & 0x0F];
+    }
+    str[size * 2] = '\0';
+
+    return (size * 2);
+}
+
+/**
+ * @brief 字符串转数组
+ * @details 字符串转字节数组
+ *
+ * @param *str 被转换的字符串
+ * @param bytes 转换出的字节数组
+ * @return 转换出的字节数组长度
+ */
+int mylib_string_to_bytes(char *str, uint8_t *bytes)
+{
+    uint8_t 	tmp, tmp1;
+    uint16_t len;
+    uint16_t dat_len;
+
+    len = strlen(str);
+    if(len % 2)				  			//检查是否为偶数
+    {
+        str[len] = '0';					//补0
+        len++;
+        str[len] = '\0';
+    }
+    dat_len = len / 2;
+    while(len)
+    {
+        if((*str > 47) && (*str < 58))	  	//0~9
+        {
+            tmp = *str - 48;
+        }
+        else if((*str > 64) && (*str < 71))	//A~F
+        {
+            tmp = *str - 55;
+        }
+        else if((*str > 96) && (*str < 103))	//a~f
+        {
+            tmp = *str - 87;
+        }
+        else
+        {
+            tmp = 32;
+        }
+        tmp <<= 4;
+        str++;
+        if((*str > 47) && (*str < 58))	  	//0~9
+        {
+            tmp1 = *str - 48;
+        }
+        else if((*str > 64) && (*str < 71))	//A~F
+        {
+            tmp1 = *str - 55;
+        }
+        else if((*str > 96) && (*str < 103))	//a~f
+        {
+            tmp1 = *str - 87;
+        }
+        else
+        {
+            tmp1 = 32;
+        }
+        tmp += tmp1;
+        *(bytes++) = tmp;
+        str++;
+        len -= 2;
+    }
+    
+    return(dat_len);
+}
+
+/**
+ * @brief 大小写转换
+ * @details 将字符串中的大写字符变为小写字符
+ *
+ * @param *str 被转换的字符串
+ * @return 转换出的字符串
+ */
+char *strlwr(char *str)
+{
+    uint16_t len;
+    char   *p;
+
+    len = strlen(str);
+    p = str;
+    while(len--)
+    {
+        if((*p > 64) && (*p < 91))
+        {
+            *p += 32;
+        }
+        p++;
+    }
+    return(str);
+}
+
+/**
+ * @brief 字符串提取数字
+ * @details 字符串提取数字字符,去除其他符号
+ *
+ * @param *str 被处理的字符串
+ * @param *num 结果字符串
+ * @return 提取出的字符串长度
+ */
+int strval(char *str, char *num)
+{
+    int len = 0;
+
+    while(*str != '\0')
+    {
+        if((*str > 47) && (*str < 58))
+        {
+            *num = *str;
+            num++;
+            len++;
+        }
+        str++;
+    }
+    *num = '\0';
+    
+    return(len);
+}
+
+/**
+ * @brief 打印16进制数据
+ * @details 由于调试时输出二进制数据
+ *
+ * @param *p 二进制数据指针
+ * @param size 数据长度
+ * @return 无
+ */
+void printk_hex(const uint8_t *p, int size)
+{
+    int i;
+
+    for(i = 0; i < size; i++)
+    {
+        printk(" %02X", *(p++));
+    }
+}
+
+/**
+ * @brief utc秒转时间
+ * @details 包含时区参数
+ *
+ * @param utc_s utc秒
+ * @param *t 转换结果
+ * @param tz 时区
+ * @return 无
+ */
+void utc_to_time(uint32_t utc_s, struct tm *t, int tz)
+{
+    #define SECOND_OF_DAY     86400      		    //1天的秒数    
+    uint16_t i, j, iDay;
+    uint32_t lDay;
+    const uint8_t DayOfMon[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
+
+    utc_s += 3600 * tz;    //时区
+
+    lDay = utc_s / SECOND_OF_DAY;
+    utc_s = utc_s % SECOND_OF_DAY;
+
+    i = 1970;										//星期取值为0-6
+    t->tm_wday = (lDay + 3) % 7;					//1970年1月1号是星期4
+    while(lDay > 365)
+    {
+        if(((i % 4 == 0) && (i % 100 != 0)) || (i % 400 == 0))    	// 闰年
+            lDay -= 366;
+        else
+            lDay -= 365;
+        i++;
+    }
+    if((lDay == 365) && !(((i % 4 == 0) && (i % 100 != 0)) || (i % 400 == 0))) //平年
+    {
+        lDay -= 365;
+        i++;
+    }
+    t->tm_year = i - 1900;     					//得到年份
+    for(j = 0; j < 12; j++)     		        //计算月份
+    {
+        if((j == 1) && (((i % 4 == 0) && (i % 100 != 0)) || (i % 400 == 0)))
+            iDay = 29;
+        else
+            iDay = DayOfMon[j];
+        if(lDay >= iDay) lDay -= iDay;
+        else break;
+    }
+    t->tm_mon  = j;
+    t->tm_mday = lDay + 1;
+    t->tm_hour = utc_s / 3600;
+    t->tm_min  = (utc_s % 3600) / 60;
+    t->tm_sec  = (utc_s % 3600) % 60;
+}
+
+/**
+ * @brief 计算日期是一年中的那一天
+ * @details 计算日期的年索引,2月当做29天算
+ *
+ * @param utc_s utc秒
+ * @param *t 转换结果
+ * @param tz 时区
+ * @return 无
+ */
+int mylib_day_index(uint8_t mon, uint8_t day)
+{
+    const  uint8_t  Line_Mon_Len[12] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
+    int index = 0;
+    int  i;
+
+    if((mon < 1) || (mon > 12))return(0); //参数判断
+    if((day < 1) || (day > 31))return(0);
+
+    for(i = 1; i < mon; i++)
+    {
+        index += Line_Mon_Len[i - 1];
+    }
+    index += day - 1;
+
+    return(index);
+}
+
+/**
+ * @brief 16进制字符串转数据
+ * @details 16进制字符串转数据,可以包含"0x"头
+ *
+ * @param *s 字符串
+ * @return 提取的数值
+ */
+int tolower(int c)  
+{  
+    if (c >= 'A' && c <= 'Z')  
+    {  
+        return c + 'a' - 'A';  
+    }  
+    else  
+    {  
+        return c;  
+    }  
+}
+
+uint32_t htoi(const char *s)  
+{  
+    int i;  
+    uint32_t n = 0; 
+
+    if (s[0] == '0' && (s[1]=='x' || s[1]=='X'))  
+    {  
+        i = 2;  
+    }  
+    else  
+    {  
+        i = 0;  
+    }  
+    for (; (s[i] >= '0' && s[i] <= '9') || (s[i] >= 'a' && s[i] <= 'z') || (s[i] >='A' && s[i] <= 'Z');++i)  
+    {  
+        if (tolower(s[i]) > '9')  
+        {  
+            n = 16 * n + (10 + tolower(s[i]) - 'a');  
+        }  
+        else  
+        {  
+            n = 16 * n + (tolower(s[i]) - '0');  
+        }  
+    }  
+    return n;  
+} 
+
+/**
+ * @brief 返回堆内存的大小
+ * @details 返回堆内存的大小
+ *
+ * @param *mp 堆内存指针
+ * @return 堆内存的大小
+ */
+uint32_t _msize(const void *mp)
+{
+    return(*((int*)((uint32_t)mp - 4)));
+}
+
+/*******************************************************************************************************
+**                            End Of File
+********************************************************************************************************/
+
+

+ 44 - 0
src/master/user/lib/mylib.h

@@ -0,0 +1,44 @@
+/*
+ * @Description: 
+ * @Version: 2.0
+ * @Author: Seven
+ * @Date: 2023-11-08 16:20:03
+ * @LastEditors: Seven
+ * @LastEditTime: 2023-11-09 11:14:45
+ */
+#ifndef __MYLIB_H
+#define __MYLIB_H
+/*********************************************************************************************************/
+#include "stdint.h"
+#include "time.h"
+#include "type.h"
+
+
+uint32_t mylib_sum(const uint8_t *p, uint16_t size);
+int mylib_memcmp(const void *p1, const void *p2, int size);
+int mylib_memcmp_b(uint8_t *p1, uint8_t value, int size);
+void mylib_uDelay(uint32_t us);
+uint16_t mylib_crc16(uint8_t *p, uint16_t size);
+void mylib_BigtoLittle16(const void *frm, void *to, uint16_t size);
+void mylib_BigtoLittle32(const void *frm, void *to, uint16_t size);
+double mylib_BigtoLittle_fp64(double dat);
+uint8_t mylib_HEXtoBCD(uint8_t hex);
+uint8_t mylib_BCDtoHEX(uint8_t bcd);
+char *itoa_(int value, char *str, uint8_t radix);
+int mylib_bytes_to_string(char *str, const uint8_t *bytes, int size);
+int mylib_string_to_bytes(char *str, uint8_t *bytes);
+char *strlwr(char *str);
+int strval(char *str, char *num);
+void printf_hex(const uint8_t *p, int size);
+void utc_to_time(uint32_t utc_s, struct tm *t, int tz);
+int mylib_day_index(uint8_t mon, uint8_t day);
+uint32_t htoi(const char *s);
+uint32_t _msize(const void *mp);
+
+
+/*********************************************************************************************************/
+#endif
+/*******************************************************************************************************
+**                            End Of File
+********************************************************************************************************/
+

+ 375 - 0
src/master/user/lzma/7zTypes.h

@@ -0,0 +1,375 @@
+/* 7zTypes.h -- Basic types
+2018-08-04 : Igor Pavlov : Public domain */
+
+#ifndef __7Z_TYPES_H
+#define __7Z_TYPES_H
+
+#ifdef _WIN32
+/* #include <windows.h> */
+#endif
+
+#include <stddef.h>
+
+#ifndef EXTERN_C_BEGIN
+#ifdef __cplusplus
+#define EXTERN_C_BEGIN extern "C" {
+#define EXTERN_C_END }
+#else
+#define EXTERN_C_BEGIN
+#define EXTERN_C_END
+#endif
+#endif
+
+EXTERN_C_BEGIN
+
+#define SZ_OK 0
+
+#define SZ_ERROR_DATA 1
+#define SZ_ERROR_MEM 2
+#define SZ_ERROR_CRC 3
+#define SZ_ERROR_UNSUPPORTED 4
+#define SZ_ERROR_PARAM 5
+#define SZ_ERROR_INPUT_EOF 6
+#define SZ_ERROR_OUTPUT_EOF 7
+#define SZ_ERROR_READ 8
+#define SZ_ERROR_WRITE 9
+#define SZ_ERROR_PROGRESS 10
+#define SZ_ERROR_FAIL 11
+#define SZ_ERROR_THREAD 12
+
+#define SZ_ERROR_ARCHIVE 16
+#define SZ_ERROR_NO_ARCHIVE 17
+
+typedef int SRes;
+
+
+#ifdef _WIN32
+
+/* typedef DWORD WRes; */
+typedef unsigned WRes;
+#define MY_SRes_HRESULT_FROM_WRes(x) HRESULT_FROM_WIN32(x)
+
+#else
+
+typedef int WRes;
+#define MY__FACILITY_WIN32 7
+#define MY__FACILITY__WRes MY__FACILITY_WIN32
+#define MY_SRes_HRESULT_FROM_WRes(x) ((HRESULT)(x) <= 0 ? ((HRESULT)(x)) : ((HRESULT) (((x) & 0x0000FFFF) | (MY__FACILITY__WRes << 16) | 0x80000000)))
+
+#endif
+
+
+#ifndef RINOK
+#define RINOK(x) { int __result__ = (x); if (__result__ != 0) return __result__; }
+#endif
+
+typedef unsigned char Byte;
+typedef short Int16;
+typedef unsigned short UInt16;
+
+#ifdef _LZMA_UINT32_IS_ULONG
+typedef long Int32;
+typedef unsigned long UInt32;
+#else
+typedef int Int32;
+typedef unsigned int UInt32;
+#endif
+
+#ifdef _SZ_NO_INT_64
+
+/* define _SZ_NO_INT_64, if your compiler doesn't support 64-bit integers.
+   NOTES: Some code will work incorrectly in that case! */
+
+typedef long Int64;
+typedef unsigned long UInt64;
+
+#else
+
+#if defined(_MSC_VER) || defined(__BORLANDC__)
+typedef __int64 Int64;
+typedef unsigned __int64 UInt64;
+#define UINT64_CONST(n) n
+#else
+typedef long long int Int64;
+typedef unsigned long long int UInt64;
+#define UINT64_CONST(n) n ## ULL
+#endif
+
+#endif
+
+#ifdef _LZMA_NO_SYSTEM_SIZE_T
+typedef UInt32 SizeT;
+#else
+typedef size_t SizeT;
+#endif
+
+typedef int BoolInt;
+/* typedef BoolInt Bool; */
+#define True 1
+#define False 0
+
+
+#ifdef _WIN32
+#define MY_STD_CALL __stdcall
+#else
+#define MY_STD_CALL
+#endif
+
+#ifdef _MSC_VER
+
+#if _MSC_VER >= 1300
+#define MY_NO_INLINE __declspec(noinline)
+#else
+#define MY_NO_INLINE
+#endif
+
+#define MY_FORCE_INLINE __forceinline
+
+#define MY_CDECL __cdecl
+#define MY_FAST_CALL __fastcall
+
+#else
+
+#define MY_NO_INLINE
+#define MY_FORCE_INLINE
+#define MY_CDECL
+#define MY_FAST_CALL
+
+/* inline keyword : for C++ / C99 */
+
+/* GCC, clang: */
+/*
+#if defined (__GNUC__) && (__GNUC__ >= 4)
+#define MY_FORCE_INLINE __attribute__((always_inline))
+#define MY_NO_INLINE __attribute__((noinline))
+#endif
+*/
+
+#endif
+
+
+/* The following interfaces use first parameter as pointer to structure */
+
+typedef struct IByteIn IByteIn;
+struct IByteIn
+{
+  Byte (*Read)(const IByteIn *p); /* reads one byte, returns 0 in case of EOF or error */
+};
+#define IByteIn_Read(p) (p)->Read(p)
+
+
+typedef struct IByteOut IByteOut;
+struct IByteOut
+{
+  void (*Write)(const IByteOut *p, Byte b);
+};
+#define IByteOut_Write(p, b) (p)->Write(p, b)
+
+
+typedef struct ISeqInStream ISeqInStream;
+struct ISeqInStream
+{
+  SRes (*Read)(const ISeqInStream *p, void *buf, size_t *size);
+    /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream.
+       (output(*size) < input(*size)) is allowed */
+};
+#define ISeqInStream_Read(p, buf, size) (p)->Read(p, buf, size)
+
+/* it can return SZ_ERROR_INPUT_EOF */
+SRes SeqInStream_Read(const ISeqInStream *stream, void *buf, size_t size);
+SRes SeqInStream_Read2(const ISeqInStream *stream, void *buf, size_t size, SRes errorType);
+SRes SeqInStream_ReadByte(const ISeqInStream *stream, Byte *buf);
+
+
+typedef struct ISeqOutStream ISeqOutStream;
+struct ISeqOutStream
+{
+  size_t (*Write)(const ISeqOutStream *p, const void *buf, size_t size);
+    /* Returns: result - the number of actually written bytes.
+       (result < size) means error */
+};
+#define ISeqOutStream_Write(p, buf, size) (p)->Write(p, buf, size)
+
+typedef enum
+{
+  SZ_SEEK_SET = 0,
+  SZ_SEEK_CUR = 1,
+  SZ_SEEK_END = 2
+} ESzSeek;
+
+
+typedef struct ISeekInStream ISeekInStream;
+struct ISeekInStream
+{
+  SRes (*Read)(const ISeekInStream *p, void *buf, size_t *size);  /* same as ISeqInStream::Read */
+  SRes (*Seek)(const ISeekInStream *p, Int64 *pos, ESzSeek origin);
+};
+#define ISeekInStream_Read(p, buf, size)   (p)->Read(p, buf, size)
+#define ISeekInStream_Seek(p, pos, origin) (p)->Seek(p, pos, origin)
+
+
+typedef struct ILookInStream ILookInStream;
+struct ILookInStream
+{
+  SRes (*Look)(const ILookInStream *p, const void **buf, size_t *size);
+    /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream.
+       (output(*size) > input(*size)) is not allowed
+       (output(*size) < input(*size)) is allowed */
+  SRes (*Skip)(const ILookInStream *p, size_t offset);
+    /* offset must be <= output(*size) of Look */
+
+  SRes (*Read)(const ILookInStream *p, void *buf, size_t *size);
+    /* reads directly (without buffer). It's same as ISeqInStream::Read */
+  SRes (*Seek)(const ILookInStream *p, Int64 *pos, ESzSeek origin);
+};
+
+#define ILookInStream_Look(p, buf, size)   (p)->Look(p, buf, size)
+#define ILookInStream_Skip(p, offset)      (p)->Skip(p, offset)
+#define ILookInStream_Read(p, buf, size)   (p)->Read(p, buf, size)
+#define ILookInStream_Seek(p, pos, origin) (p)->Seek(p, pos, origin)
+
+
+SRes LookInStream_LookRead(const ILookInStream *stream, void *buf, size_t *size);
+SRes LookInStream_SeekTo(const ILookInStream *stream, UInt64 offset);
+
+/* reads via ILookInStream::Read */
+SRes LookInStream_Read2(const ILookInStream *stream, void *buf, size_t size, SRes errorType);
+SRes LookInStream_Read(const ILookInStream *stream, void *buf, size_t size);
+
+
+
+typedef struct
+{
+  ILookInStream vt;
+  const ISeekInStream *realStream;
+ 
+  size_t pos;
+  size_t size; /* it's data size */
+  
+  /* the following variables must be set outside */
+  Byte *buf;
+  size_t bufSize;
+} CLookToRead2;
+
+void LookToRead2_CreateVTable(CLookToRead2 *p, int lookahead);
+
+#define LookToRead2_Init(p) { (p)->pos = (p)->size = 0; }
+
+
+typedef struct
+{
+  ISeqInStream vt;
+  const ILookInStream *realStream;
+} CSecToLook;
+
+void SecToLook_CreateVTable(CSecToLook *p);
+
+
+
+typedef struct
+{
+  ISeqInStream vt;
+  const ILookInStream *realStream;
+} CSecToRead;
+
+void SecToRead_CreateVTable(CSecToRead *p);
+
+
+typedef struct ICompressProgress ICompressProgress;
+
+struct ICompressProgress
+{
+  SRes (*Progress)(const ICompressProgress *p, UInt64 inSize, UInt64 outSize);
+    /* Returns: result. (result != SZ_OK) means break.
+       Value (UInt64)(Int64)-1 for size means unknown value. */
+};
+#define ICompressProgress_Progress(p, inSize, outSize) (p)->Progress(p, inSize, outSize)
+
+
+
+typedef struct ISzAlloc ISzAlloc;
+typedef const ISzAlloc * ISzAllocPtr;
+
+struct ISzAlloc
+{
+  void *(*Alloc)(ISzAllocPtr p, size_t size);
+  void (*Free)(ISzAllocPtr p, void *address); /* address can be 0 */
+};
+
+#define ISzAlloc_Alloc(p, size) (p)->Alloc(p, size)
+#define ISzAlloc_Free(p, a) (p)->Free(p, a)
+
+/* deprecated */
+#define IAlloc_Alloc(p, size) ISzAlloc_Alloc(p, size)
+#define IAlloc_Free(p, a) ISzAlloc_Free(p, a)
+
+
+
+
+
+#ifndef MY_offsetof
+  #ifdef offsetof
+    #define MY_offsetof(type, m) offsetof(type, m)
+    /*
+    #define MY_offsetof(type, m) FIELD_OFFSET(type, m)
+    */
+  #else
+    #define MY_offsetof(type, m) ((size_t)&(((type *)0)->m))
+  #endif
+#endif
+
+
+
+#ifndef MY_container_of
+
+/*
+#define MY_container_of(ptr, type, m) container_of(ptr, type, m)
+#define MY_container_of(ptr, type, m) CONTAINING_RECORD(ptr, type, m)
+#define MY_container_of(ptr, type, m) ((type *)((char *)(ptr) - offsetof(type, m)))
+#define MY_container_of(ptr, type, m) (&((type *)0)->m == (ptr), ((type *)(((char *)(ptr)) - MY_offsetof(type, m))))
+*/
+
+/*
+  GCC shows warning: "perhaps the 'offsetof' macro was used incorrectly"
+    GCC 3.4.4 : classes with constructor
+    GCC 4.8.1 : classes with non-public variable members"
+*/
+
+// #define MY_container_of(ptr, type, m) ((type *)((char *)(1 ? (ptr) : &((type *)0)->m) - MY_offsetof(type, m)))
+
+
+#endif
+
+#define CONTAINER_FROM_VTBL_SIMPLE(ptr, type, m) ((type *)(ptr))
+
+/*
+#define CONTAINER_FROM_VTBL(ptr, type, m) CONTAINER_FROM_VTBL_SIMPLE(ptr, type, m)
+*/
+// #define CONTAINER_FROM_VTBL(ptr, type, m) MY_container_of(ptr, type, m)
+
+#define CONTAINER_FROM_VTBL_CLS(ptr, type, m) CONTAINER_FROM_VTBL_SIMPLE(ptr, type, m)
+/*
+#define CONTAINER_FROM_VTBL_CLS(ptr, type, m) CONTAINER_FROM_VTBL(ptr, type, m)
+*/
+
+
+
+#ifdef _WIN32
+
+#define CHAR_PATH_SEPARATOR '\\'
+#define WCHAR_PATH_SEPARATOR L'\\'
+#define STRING_PATH_SEPARATOR "\\"
+#define WSTRING_PATH_SEPARATOR L"\\"
+
+#else
+
+#define CHAR_PATH_SEPARATOR '/'
+#define WCHAR_PATH_SEPARATOR L'/'
+#define STRING_PATH_SEPARATOR "/"
+#define WSTRING_PATH_SEPARATOR L"/"
+
+#endif
+
+EXTERN_C_END
+
+#endif

+ 33 - 0
src/master/user/lzma/Compiler.h

@@ -0,0 +1,33 @@
+/* Compiler.h
+2017-04-03 : Igor Pavlov : Public domain */
+
+#ifndef __7Z_COMPILER_H
+#define __7Z_COMPILER_H
+
+#ifdef _MSC_VER
+
+  #ifdef UNDER_CE
+    #define RPC_NO_WINDOWS_H
+    /* #pragma warning(disable : 4115) // '_RPC_ASYNC_STATE' : named type definition in parentheses */
+    #pragma warning(disable : 4201) // nonstandard extension used : nameless struct/union
+    #pragma warning(disable : 4214) // nonstandard extension used : bit field types other than int
+  #endif
+
+  #if _MSC_VER >= 1300
+    #pragma warning(disable : 4996) // This function or variable may be unsafe
+  #else
+    #pragma warning(disable : 4511) // copy constructor could not be generated
+    #pragma warning(disable : 4512) // assignment operator could not be generated
+    #pragma warning(disable : 4514) // unreferenced inline function has been removed
+    #pragma warning(disable : 4702) // unreachable code
+    #pragma warning(disable : 4710) // not inlined
+    #pragma warning(disable : 4714) // function marked as __forceinline not inlined
+    #pragma warning(disable : 4786) // identifier was truncated to '255' characters in the debug information
+  #endif
+
+#endif
+
+#define UNUSED_VAR(x) (void)x;
+/* #define UNUSED_VAR(x) x=x; */
+
+#endif

+ 1128 - 0
src/master/user/lzma/LzFind.c

@@ -0,0 +1,1128 @@
+/* LzFind.c -- Match finder for LZ algorithms
+2018-07-08 : Igor Pavlov : Public domain */
+
+#include "Precomp.h"
+
+#include <string.h>
+
+#include "LzFind.h"
+#include "LzHash.h"
+
+#define kEmptyHashValue 0
+#define kMaxValForNormalize ((UInt32)0xFFFFFFFF)
+#define kNormalizeStepMin (1 << 10) /* it must be power of 2 */
+#define kNormalizeMask (~(UInt32)(kNormalizeStepMin - 1))
+#define kMaxHistorySize ((UInt32)7 << 29)
+
+#define kStartMaxLen 3
+
+static void LzInWindow_Free(CMatchFinder *p, ISzAllocPtr alloc)
+{
+    if (!p->directInput)
+    {
+        ISzAlloc_Free(alloc, p->bufferBase);
+        p->bufferBase = NULL;
+    }
+}
+
+/* keepSizeBefore + keepSizeAfter + keepSizeReserv must be < 4G) */
+
+static int LzInWindow_Create(CMatchFinder *p, UInt32 keepSizeReserv, ISzAllocPtr alloc)
+{
+    UInt32 blockSize = p->keepSizeBefore + p->keepSizeAfter + keepSizeReserv;
+    if (p->directInput)
+    {
+        p->blockSize = blockSize;
+        return 1;
+    }
+    if (!p->bufferBase || p->blockSize != blockSize)
+    {
+        LzInWindow_Free(p, alloc);
+        p->blockSize = blockSize;
+        p->bufferBase = (Byte *) ISzAlloc_Alloc(alloc, (size_t) blockSize);
+    }
+    return (p->bufferBase != NULL);
+}
+
+Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p)
+{
+    return p->buffer;
+}
+
+UInt32 MatchFinder_GetNumAvailableBytes(CMatchFinder *p)
+{
+    return p->streamPos - p->pos;
+}
+
+void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue)
+{
+    p->posLimit -= subValue;
+    p->pos -= subValue;
+    p->streamPos -= subValue;
+}
+
+static void MatchFinder_ReadBlock(CMatchFinder *p)
+{
+    if (p->streamEndWasReached || p->result != SZ_OK)
+        return;
+
+    /* We use (p->streamPos - p->pos) value. (p->streamPos < p->pos) is allowed. */
+
+    if (p->directInput)
+    {
+        UInt32 curSize = 0xFFFFFFFF - (p->streamPos - p->pos);
+        if (curSize > p->directInputRem)
+            curSize = (UInt32) p->directInputRem;
+        p->directInputRem -= curSize;
+        p->streamPos += curSize;
+        if (p->directInputRem == 0)
+            p->streamEndWasReached = 1;
+        return;
+    }
+
+    for (;;)
+    {
+        Byte *dest = p->buffer + (p->streamPos - p->pos);
+        size_t size = (p->bufferBase + p->blockSize - dest);
+        if (size == 0)
+            return;
+
+        p->result = ISeqInStream_Read(p->stream, dest, &size);
+        if (p->result != SZ_OK)
+            return;
+        if (size == 0)
+        {
+            p->streamEndWasReached = 1;
+            return;
+        }
+        p->streamPos += (UInt32) size;
+        if (p->streamPos - p->pos > p->keepSizeAfter)
+            return;
+    }
+}
+
+void MatchFinder_MoveBlock(CMatchFinder *p)
+{
+    memmove(p->bufferBase,
+            p->buffer - p->keepSizeBefore,
+            (size_t) (p->streamPos - p->pos) + p->keepSizeBefore);
+    p->buffer = p->bufferBase + p->keepSizeBefore;
+}
+
+int MatchFinder_NeedMove(CMatchFinder *p)
+{
+    if (p->directInput)
+        return 0;
+    /* if (p->streamEndWasReached) return 0; */
+    return ((size_t) (p->bufferBase + p->blockSize - p->buffer) <= p->keepSizeAfter);
+}
+
+void MatchFinder_ReadIfRequired(CMatchFinder *p)
+{
+    if (p->streamEndWasReached)
+        return;
+    if (p->keepSizeAfter >= p->streamPos - p->pos)
+        MatchFinder_ReadBlock(p);
+}
+
+static void MatchFinder_CheckAndMoveAndRead(CMatchFinder *p)
+{
+    if (MatchFinder_NeedMove(p))
+        MatchFinder_MoveBlock(p);
+    MatchFinder_ReadBlock(p);
+}
+
+static void MatchFinder_SetDefaultSettings(CMatchFinder *p)
+{
+    p->cutValue = 32;
+    p->btMode = 1;
+    p->numHashBytes = 4;
+    p->bigHash = 0;
+}
+
+#define kCrcPoly 0xEDB88320
+
+void MatchFinder_Construct(CMatchFinder *p)
+{
+    unsigned i;
+    p->bufferBase = NULL;
+    p->directInput = 0;
+    p->hash = NULL;
+    p->expectedDataSize = (UInt64) (Int64) - 1;
+    MatchFinder_SetDefaultSettings(p);
+
+    for (i = 0; i < 256; i++)
+    {
+        UInt32 r = (UInt32) i;
+        unsigned j;
+        for (j = 0; j < 8; j++)
+            r = (r >> 1) ^ (kCrcPoly & ((UInt32) 0 - (r & 1)));
+        p->crc[i] = r;
+    }
+}
+
+static void MatchFinder_FreeThisClassMemory(CMatchFinder *p, ISzAllocPtr alloc)
+{
+    ISzAlloc_Free(alloc, p->hash);
+    p->hash = NULL;
+}
+
+void MatchFinder_Free(CMatchFinder *p, ISzAllocPtr alloc)
+{
+    MatchFinder_FreeThisClassMemory(p, alloc);
+    LzInWindow_Free(p, alloc);
+}
+
+static CLzRef* AllocRefs(size_t num, ISzAllocPtr alloc)
+{
+    size_t sizeInBytes = (size_t) num * sizeof (CLzRef);
+    if (sizeInBytes / sizeof (CLzRef) != num)
+        return NULL;
+    return (CLzRef *) ISzAlloc_Alloc(alloc, sizeInBytes);
+}
+
+int MatchFinder_Create(CMatchFinder *p, UInt32 historySize,
+                       UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter,
+                       ISzAllocPtr alloc)
+{
+    UInt32 sizeReserv;
+
+    if (historySize > kMaxHistorySize)
+    {
+        MatchFinder_Free(p, alloc);
+        return 0;
+    }
+
+    sizeReserv = historySize >> 1;
+    if (historySize >= ((UInt32) 3 << 30)) sizeReserv = historySize >> 3;
+    else if (historySize >= ((UInt32) 2 << 30)) sizeReserv = historySize >> 2;
+
+    sizeReserv += (keepAddBufferBefore + matchMaxLen + keepAddBufferAfter) / 2 + (1 << 19);
+
+    p->keepSizeBefore = historySize + keepAddBufferBefore + 1;
+    p->keepSizeAfter = matchMaxLen + keepAddBufferAfter;
+
+    /* we need one additional byte, since we use MoveBlock after pos++ and before dictionary using */
+
+    if (LzInWindow_Create(p, sizeReserv, alloc))
+    {
+        UInt32 newCyclicBufferSize = historySize + 1;
+        UInt32 hs;
+        p->matchMaxLen = matchMaxLen;
+        {
+            p->fixedHashSize = 0;
+            if (p->numHashBytes == 2)
+                hs = (1 << 16) - 1;
+            else
+            {
+                hs = historySize;
+                if (hs > p->expectedDataSize)
+                    hs = (UInt32) p->expectedDataSize;
+                if (hs != 0)
+                    hs--;
+                hs |= (hs >> 1);
+                hs |= (hs >> 2);
+                hs |= (hs >> 4);
+                hs |= (hs >> 8);
+                hs >>= 1;
+                hs |= 0xFFFF; /* don't change it! It's required for Deflate */
+                if (hs > (1 << 24))
+                {
+                    if (p->numHashBytes == 3)
+                        hs = (1 << 24) - 1;
+                    else
+                        hs >>= 1;
+                    /* if (bigHash) mode, GetHeads4b() in LzFindMt.c needs (hs >= ((1 << 24) - 1))) */
+                }
+            }
+            p->hashMask = hs;
+            hs++;
+            if (p->numHashBytes > 2) p->fixedHashSize += kHash2Size;
+            if (p->numHashBytes > 3) p->fixedHashSize += kHash3Size;
+            if (p->numHashBytes > 4) p->fixedHashSize += kHash4Size;
+            hs += p->fixedHashSize;
+        }
+
+        {
+            size_t newSize;
+            size_t numSons;
+            p->historySize = historySize;
+            p->hashSizeSum = hs;
+            p->cyclicBufferSize = newCyclicBufferSize;
+
+            numSons = newCyclicBufferSize;
+            if (p->btMode)
+                numSons <<= 1;
+            newSize = hs + numSons;
+
+            if (p->hash && p->numRefs == newSize)
+                return 1;
+
+            MatchFinder_FreeThisClassMemory(p, alloc);
+            p->numRefs = newSize;
+            p->hash = AllocRefs(newSize, alloc);
+
+            if (p->hash)
+            {
+                p->son = p->hash + p->hashSizeSum;
+                return 1;
+            }
+        }
+    }
+
+    MatchFinder_Free(p, alloc);
+    return 0;
+}
+
+static void MatchFinder_SetLimits(CMatchFinder *p)
+{
+    UInt32 limit = kMaxValForNormalize - p->pos;
+    UInt32 limit2 = p->cyclicBufferSize - p->cyclicBufferPos;
+
+    if (limit2 < limit)
+        limit = limit2;
+    limit2 = p->streamPos - p->pos;
+
+    if (limit2 <= p->keepSizeAfter)
+    {
+        if (limit2 > 0)
+            limit2 = 1;
+    }
+    else
+        limit2 -= p->keepSizeAfter;
+
+    if (limit2 < limit)
+        limit = limit2;
+
+    {
+        UInt32 lenLimit = p->streamPos - p->pos;
+        if (lenLimit > p->matchMaxLen)
+            lenLimit = p->matchMaxLen;
+        p->lenLimit = lenLimit;
+    }
+    p->posLimit = p->pos + limit;
+}
+
+void MatchFinder_Init_LowHash(CMatchFinder *p)
+{
+    size_t i;
+    CLzRef *items = p->hash;
+    size_t numItems = p->fixedHashSize;
+    for (i = 0; i < numItems; i++)
+        items[i] = kEmptyHashValue;
+}
+
+void MatchFinder_Init_HighHash(CMatchFinder *p)
+{
+    size_t i;
+    CLzRef *items = p->hash + p->fixedHashSize;
+    size_t numItems = (size_t) p->hashMask + 1;
+    for (i = 0; i < numItems; i++)
+        items[i] = kEmptyHashValue;
+}
+
+void MatchFinder_Init_3(CMatchFinder *p, int readData)
+{
+    p->cyclicBufferPos = 0;
+    p->buffer = p->bufferBase;
+    p->pos =
+            p->streamPos = p->cyclicBufferSize;
+    p->result = SZ_OK;
+    p->streamEndWasReached = 0;
+
+    if (readData)
+        MatchFinder_ReadBlock(p);
+
+    MatchFinder_SetLimits(p);
+}
+
+void MatchFinder_Init(CMatchFinder *p)
+{
+    MatchFinder_Init_HighHash(p);
+    MatchFinder_Init_LowHash(p);
+    MatchFinder_Init_3(p, True);
+}
+
+static UInt32 MatchFinder_GetSubValue(CMatchFinder *p)
+{
+    return (p->pos - p->historySize - 1) & kNormalizeMask;
+}
+
+void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, size_t numItems)
+{
+    size_t i;
+    for (i = 0; i < numItems; i++)
+    {
+        UInt32 value = items[i];
+        if (value <= subValue)
+            value = kEmptyHashValue;
+        else
+            value -= subValue;
+        items[i] = value;
+    }
+}
+
+static void MatchFinder_Normalize(CMatchFinder *p)
+{
+    UInt32 subValue = MatchFinder_GetSubValue(p);
+    MatchFinder_Normalize3(subValue, p->hash, p->numRefs);
+    MatchFinder_ReduceOffsets(p, subValue);
+}
+
+MY_NO_INLINE
+static void MatchFinder_CheckLimits(CMatchFinder *p)
+{
+    if (p->pos == kMaxValForNormalize)
+        MatchFinder_Normalize(p);
+    if (!p->streamEndWasReached && p->keepSizeAfter == p->streamPos - p->pos)
+        MatchFinder_CheckAndMoveAndRead(p);
+    if (p->cyclicBufferPos == p->cyclicBufferSize)
+        p->cyclicBufferPos = 0;
+    MatchFinder_SetLimits(p);
+}
+
+/*
+  (lenLimit > maxLen)
+ */
+MY_FORCE_INLINE
+static UInt32 * Hc_GetMatchesSpec(unsigned lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son,
+                                  UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue,
+                                  UInt32 *distances, unsigned maxLen)
+{
+    /*
+    son[_cyclicBufferPos] = curMatch;
+    for (;;)
+    {
+      UInt32 delta = pos - curMatch;
+      if (cutValue-- == 0 || delta >= _cyclicBufferSize)
+        return distances;
+      {
+        const Byte *pb = cur - delta;
+        curMatch = son[_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)];
+        if (pb[maxLen] == cur[maxLen] && *pb == *cur)
+        {
+          UInt32 len = 0;
+          while (++len != lenLimit)
+            if (pb[len] != cur[len])
+              break;
+          if (maxLen < len)
+          {
+            maxLen = len;
+     *distances++ = len;
+     *distances++ = delta - 1;
+            if (len == lenLimit)
+              return distances;
+          }
+        }
+      }
+    }
+     */
+
+    const Byte *lim = cur + lenLimit;
+    son[_cyclicBufferPos] = curMatch;
+    do
+    {
+        UInt32 delta = pos - curMatch;
+        if (delta >= _cyclicBufferSize)
+            break;
+        {
+            ptrdiff_t diff;
+            curMatch = son[_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)];
+            diff = (ptrdiff_t) 0 - delta;
+            if (cur[maxLen] == cur[maxLen + diff])
+            {
+                const Byte *c = cur;
+                while (*c == c[diff])
+                {
+                    if (++c == lim)
+                    {
+                        distances[0] = (UInt32) (lim - cur);
+                        distances[1] = delta - 1;
+                        return distances + 2;
+                    }
+                }
+                {
+                    unsigned len = (unsigned) (c - cur);
+                    if (maxLen < len)
+                    {
+                        maxLen = len;
+                        distances[0] = (UInt32) len;
+                        distances[1] = delta - 1;
+                        distances += 2;
+                    }
+                }
+            }
+        }
+    }
+    while (--cutValue);
+
+    return distances;
+}
+
+MY_FORCE_INLINE
+UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son,
+                         UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue,
+                         UInt32 *distances, UInt32 maxLen)
+{
+    CLzRef *ptr0 = son + ((size_t) _cyclicBufferPos << 1) + 1;
+    CLzRef *ptr1 = son + ((size_t) _cyclicBufferPos << 1);
+    unsigned len0 = 0, len1 = 0;
+    for (;;)
+    {
+        UInt32 delta = pos - curMatch;
+        if (cutValue-- == 0 || delta >= _cyclicBufferSize)
+        {
+            *ptr0 = *ptr1 = kEmptyHashValue;
+            return distances;
+        }
+        {
+            CLzRef *pair = son + ((size_t) (_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1);
+            const Byte *pb = cur - delta;
+            unsigned len = (len0 < len1 ? len0 : len1);
+            UInt32 pair0 = pair[0];
+            if (pb[len] == cur[len])
+            {
+                if (++len != lenLimit && pb[len] == cur[len])
+                    while (++len != lenLimit)
+                        if (pb[len] != cur[len])
+                            break;
+                if (maxLen < len)
+                {
+                    maxLen = (UInt32) len;
+                    *distances++ = (UInt32) len;
+                    *distances++ = delta - 1;
+                    if (len == lenLimit)
+                    {
+                        *ptr1 = pair0;
+                        *ptr0 = pair[1];
+                        return distances;
+                    }
+                }
+            }
+            if (pb[len] < cur[len])
+            {
+                *ptr1 = curMatch;
+                ptr1 = pair + 1;
+                curMatch = *ptr1;
+                len1 = len;
+            }
+            else
+            {
+                *ptr0 = curMatch;
+                ptr0 = pair;
+                curMatch = *ptr0;
+                len0 = len;
+            }
+        }
+    }
+}
+
+static void SkipMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son,
+                            UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue)
+{
+    CLzRef *ptr0 = son + ((size_t) _cyclicBufferPos << 1) + 1;
+    CLzRef *ptr1 = son + ((size_t) _cyclicBufferPos << 1);
+    unsigned len0 = 0, len1 = 0;
+    for (;;)
+    {
+        UInt32 delta = pos - curMatch;
+        if (cutValue-- == 0 || delta >= _cyclicBufferSize)
+        {
+            *ptr0 = *ptr1 = kEmptyHashValue;
+            return;
+        }
+        {
+            CLzRef *pair = son + ((size_t) (_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1);
+            const Byte *pb = cur - delta;
+            unsigned len = (len0 < len1 ? len0 : len1);
+            if (pb[len] == cur[len])
+            {
+                while (++len != lenLimit)
+                    if (pb[len] != cur[len])
+                        break;
+                {
+                    if (len == lenLimit)
+                    {
+                        *ptr1 = pair[0];
+                        *ptr0 = pair[1];
+                        return;
+                    }
+                }
+            }
+            if (pb[len] < cur[len])
+            {
+                *ptr1 = curMatch;
+                ptr1 = pair + 1;
+                curMatch = *ptr1;
+                len1 = len;
+            }
+            else
+            {
+                *ptr0 = curMatch;
+                ptr0 = pair;
+                curMatch = *ptr0;
+                len0 = len;
+            }
+        }
+    }
+}
+
+#define MOVE_POS \
+  ++p->cyclicBufferPos; \
+  p->buffer++; \
+  if (++p->pos == p->posLimit) MatchFinder_CheckLimits(p);
+
+#define MOVE_POS_RET MOVE_POS return (UInt32)offset;
+
+static void MatchFinder_MovePos(CMatchFinder *p)
+{
+    MOVE_POS;
+}
+
+#define GET_MATCHES_HEADER2(minLen, ret_op) \
+  unsigned lenLimit; UInt32 hv; const Byte *cur; UInt32 curMatch; \
+  lenLimit = (unsigned)p->lenLimit; { if (lenLimit < minLen) { MatchFinder_MovePos(p); ret_op; }} \
+  cur = p->buffer;
+
+#define GET_MATCHES_HEADER(minLen) GET_MATCHES_HEADER2(minLen, return 0)
+#define SKIP_HEADER(minLen)        GET_MATCHES_HEADER2(minLen, continue)
+
+#define MF_PARAMS(p) p->pos, p->buffer, p->son, p->cyclicBufferPos, p->cyclicBufferSize, p->cutValue
+
+#define GET_MATCHES_FOOTER(offset, maxLen) \
+  offset = (unsigned)(GetMatchesSpec1((UInt32)lenLimit, curMatch, MF_PARAMS(p), \
+  distances + offset, (UInt32)maxLen) - distances); MOVE_POS_RET;
+
+#define SKIP_FOOTER \
+  SkipMatchesSpec((UInt32)lenLimit, curMatch, MF_PARAMS(p)); MOVE_POS;
+
+#define UPDATE_maxLen { \
+    ptrdiff_t diff = (ptrdiff_t)0 - d2; \
+    const Byte *c = cur + maxLen; \
+    const Byte *lim = cur + lenLimit; \
+    for (; c != lim; c++) if (*(c + diff) != *c) break; \
+    maxLen = (unsigned)(c - cur); }
+
+static UInt32 Bt2_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
+{
+    unsigned offset;
+    GET_MATCHES_HEADER(2)
+    HASH2_CALC;
+    curMatch = p->hash[hv];
+    p->hash[hv] = p->pos;
+    offset = 0;
+    GET_MATCHES_FOOTER(offset, 1)
+}
+
+UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
+{
+    unsigned offset;
+    GET_MATCHES_HEADER(3)
+    HASH_ZIP_CALC;
+    curMatch = p->hash[hv];
+    p->hash[hv] = p->pos;
+    offset = 0;
+    GET_MATCHES_FOOTER(offset, 2)
+}
+
+static UInt32 Bt3_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
+{
+    UInt32 h2, d2, pos;
+    unsigned maxLen, offset;
+    UInt32 *hash;
+    GET_MATCHES_HEADER(3)
+
+    HASH3_CALC;
+
+    hash = p->hash;
+    pos = p->pos;
+
+    d2 = pos - hash[h2];
+
+    curMatch = (hash + kFix3HashSize)[hv];
+
+    hash[h2] = pos;
+    (hash + kFix3HashSize)[hv] = pos;
+
+    maxLen = 2;
+    offset = 0;
+
+    if (d2 < p->cyclicBufferSize && *(cur - d2) == *cur)
+    {
+        UPDATE_maxLen
+        distances[0] = (UInt32) maxLen;
+        distances[1] = d2 - 1;
+        offset = 2;
+        if (maxLen == lenLimit)
+        {
+            SkipMatchesSpec((UInt32) lenLimit, curMatch, MF_PARAMS(p));
+            MOVE_POS_RET;
+        }
+    }
+
+    GET_MATCHES_FOOTER(offset, maxLen)
+}
+
+static UInt32 Bt4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
+{
+    UInt32 h2, h3, d2, d3, pos;
+    unsigned maxLen, offset;
+    UInt32 *hash;
+    GET_MATCHES_HEADER(4)
+
+    HASH4_CALC;
+
+    hash = p->hash;
+    pos = p->pos;
+
+    d2 = pos - hash [h2];
+    d3 = pos - (hash + kFix3HashSize)[h3];
+
+    curMatch = (hash + kFix4HashSize)[hv];
+
+    hash [h2] = pos;
+    (hash + kFix3HashSize)[h3] = pos;
+    (hash + kFix4HashSize)[hv] = pos;
+
+    maxLen = 0;
+    offset = 0;
+
+    if (d2 < p->cyclicBufferSize && *(cur - d2) == *cur)
+    {
+        maxLen = 2;
+        distances[0] = 2;
+        distances[1] = d2 - 1;
+        offset = 2;
+    }
+
+    if (d2 != d3 && d3 < p->cyclicBufferSize && *(cur - d3) == *cur)
+    {
+        maxLen = 3;
+        distances[(size_t) offset + 1] = d3 - 1;
+        offset += 2;
+        d2 = d3;
+    }
+
+    if (offset != 0)
+    {
+        UPDATE_maxLen
+        distances[(size_t) offset - 2] = (UInt32) maxLen;
+        if (maxLen == lenLimit)
+        {
+            SkipMatchesSpec((UInt32) lenLimit, curMatch, MF_PARAMS(p));
+            MOVE_POS_RET;
+        }
+    }
+
+    if (maxLen < 3)
+        maxLen = 3;
+
+    GET_MATCHES_FOOTER(offset, maxLen)
+}
+
+/*
+static UInt32 Bt5_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
+{
+  UInt32 h2, h3, h4, d2, d3, d4, maxLen, offset, pos;
+  UInt32 *hash;
+  GET_MATCHES_HEADER(5)
+
+  HASH5_CALC;
+
+  hash = p->hash;
+  pos = p->pos;
+
+  d2 = pos - hash                  [h2];
+  d3 = pos - (hash + kFix3HashSize)[h3];
+  d4 = pos - (hash + kFix4HashSize)[h4];
+
+  curMatch = (hash + kFix5HashSize)[hv];
+
+  hash                  [h2] = pos;
+  (hash + kFix3HashSize)[h3] = pos;
+  (hash + kFix4HashSize)[h4] = pos;
+  (hash + kFix5HashSize)[hv] = pos;
+
+  maxLen = 0;
+  offset = 0;
+
+  if (d2 < p->cyclicBufferSize && *(cur - d2) == *cur)
+  {
+    distances[0] = maxLen = 2;
+    distances[1] = d2 - 1;
+    offset = 2;
+    if (*(cur - d2 + 2) == cur[2])
+      distances[0] = maxLen = 3;
+    else if (d3 < p->cyclicBufferSize && *(cur - d3) == *cur)
+    {
+      distances[2] = maxLen = 3;
+      distances[3] = d3 - 1;
+      offset = 4;
+      d2 = d3;
+    }
+  }
+  else if (d3 < p->cyclicBufferSize && *(cur - d3) == *cur)
+  {
+    distances[0] = maxLen = 3;
+    distances[1] = d3 - 1;
+    offset = 2;
+    d2 = d3;
+  }
+  
+  if (d2 != d4 && d4 < p->cyclicBufferSize
+      && *(cur - d4) == *cur
+      && *(cur - d4 + 3) == *(cur + 3))
+  {
+    maxLen = 4;
+    distances[(size_t)offset + 1] = d4 - 1;
+    offset += 2;
+    d2 = d4;
+  }
+  
+  if (offset != 0)
+  {
+    UPDATE_maxLen
+    distances[(size_t)offset - 2] = maxLen;
+    if (maxLen == lenLimit)
+    {
+      SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p));
+      MOVE_POS_RET;
+    }
+  }
+
+  if (maxLen < 4)
+    maxLen = 4;
+  
+  GET_MATCHES_FOOTER(offset, maxLen)
+}
+ */
+
+static UInt32 Hc4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
+{
+    UInt32 h2, h3, d2, d3, pos;
+    unsigned maxLen, offset;
+    UInt32 *hash;
+    GET_MATCHES_HEADER(4)
+
+    HASH4_CALC;
+
+    hash = p->hash;
+    pos = p->pos;
+
+    d2 = pos - hash [h2];
+    d3 = pos - (hash + kFix3HashSize)[h3];
+    curMatch = (hash + kFix4HashSize)[hv];
+
+    hash [h2] = pos;
+    (hash + kFix3HashSize)[h3] = pos;
+    (hash + kFix4HashSize)[hv] = pos;
+
+    maxLen = 0;
+    offset = 0;
+
+    if (d2 < p->cyclicBufferSize && *(cur - d2) == *cur)
+    {
+        maxLen = 2;
+        distances[0] = 2;
+        distances[1] = d2 - 1;
+        offset = 2;
+    }
+
+    if (d2 != d3 && d3 < p->cyclicBufferSize && *(cur - d3) == *cur)
+    {
+        maxLen = 3;
+        distances[(size_t) offset + 1] = d3 - 1;
+        offset += 2;
+        d2 = d3;
+    }
+
+    if (offset != 0)
+    {
+        UPDATE_maxLen
+        distances[(size_t) offset - 2] = (UInt32) maxLen;
+        if (maxLen == lenLimit)
+        {
+            p->son[p->cyclicBufferPos] = curMatch;
+            MOVE_POS_RET;
+        }
+    }
+
+    if (maxLen < 3)
+        maxLen = 3;
+
+    offset = (unsigned) (Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p),
+                                           distances + offset, maxLen) - (distances));
+    MOVE_POS_RET
+}
+
+/*
+static UInt32 Hc5_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
+{
+  UInt32 h2, h3, h4, d2, d3, d4, maxLen, offset, pos
+  UInt32 *hash;
+  GET_MATCHES_HEADER(5)
+
+  HASH5_CALC;
+
+  hash = p->hash;
+  pos = p->pos;
+  
+  d2 = pos - hash                  [h2];
+  d3 = pos - (hash + kFix3HashSize)[h3];
+  d4 = pos - (hash + kFix4HashSize)[h4];
+
+  curMatch = (hash + kFix5HashSize)[hv];
+
+  hash                  [h2] = pos;
+  (hash + kFix3HashSize)[h3] = pos;
+  (hash + kFix4HashSize)[h4] = pos;
+  (hash + kFix5HashSize)[hv] = pos;
+
+  maxLen = 0;
+  offset = 0;
+
+  if (d2 < p->cyclicBufferSize && *(cur - d2) == *cur)
+  {
+    distances[0] = maxLen = 2;
+    distances[1] = d2 - 1;
+    offset = 2;
+    if (*(cur - d2 + 2) == cur[2])
+      distances[0] = maxLen = 3;
+    else if (d3 < p->cyclicBufferSize && *(cur - d3) == *cur)
+    {
+      distances[2] = maxLen = 3;
+      distances[3] = d3 - 1;
+      offset = 4;
+      d2 = d3;
+    }
+  }
+  else if (d3 < p->cyclicBufferSize && *(cur - d3) == *cur)
+  {
+    distances[0] = maxLen = 3;
+    distances[1] = d3 - 1;
+    offset = 2;
+    d2 = d3;
+  }
+  
+  if (d2 != d4 && d4 < p->cyclicBufferSize
+      && *(cur - d4) == *cur
+      && *(cur - d4 + 3) == *(cur + 3))
+  {
+    maxLen = 4;
+    distances[(size_t)offset + 1] = d4 - 1;
+    offset += 2;
+    d2 = d4;
+  }
+  
+  if (offset != 0)
+  {
+    UPDATE_maxLen
+    distances[(size_t)offset - 2] = maxLen;
+    if (maxLen == lenLimit)
+    {
+      p->son[p->cyclicBufferPos] = curMatch;
+      MOVE_POS_RET;
+    }
+  }
+  
+  if (maxLen < 4)
+    maxLen = 4;
+
+  offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p),
+      distances + offset, maxLen) - (distances));
+  MOVE_POS_RET
+}
+ */
+
+UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
+{
+    unsigned offset;
+    GET_MATCHES_HEADER(3)
+    HASH_ZIP_CALC;
+    curMatch = p->hash[hv];
+    p->hash[hv] = p->pos;
+    offset = (unsigned) (Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p),
+                                           distances, 2) - (distances));
+    MOVE_POS_RET
+}
+
+static void Bt2_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
+{
+    do
+    {
+        SKIP_HEADER(2)
+        HASH2_CALC;
+        curMatch = p->hash[hv];
+        p->hash[hv] = p->pos;
+        SKIP_FOOTER
+    }
+    while (--num != 0);
+}
+
+void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
+{
+    do
+    {
+        SKIP_HEADER(3)
+        HASH_ZIP_CALC;
+        curMatch = p->hash[hv];
+        p->hash[hv] = p->pos;
+        SKIP_FOOTER
+    }
+    while (--num != 0);
+}
+
+static void Bt3_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
+{
+    do
+    {
+        UInt32 h2;
+        UInt32 *hash;
+        SKIP_HEADER(3)
+        HASH3_CALC;
+        hash = p->hash;
+        curMatch = (hash + kFix3HashSize)[hv];
+        hash[h2] =
+                (hash + kFix3HashSize)[hv] = p->pos;
+        SKIP_FOOTER
+    }
+    while (--num != 0);
+}
+
+static void Bt4_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
+{
+    do
+    {
+        UInt32 h2, h3;
+        UInt32 *hash;
+        SKIP_HEADER(4)
+        HASH4_CALC;
+        hash = p->hash;
+        curMatch = (hash + kFix4HashSize)[hv];
+        hash [h2] =
+                (hash + kFix3HashSize)[h3] =
+                (hash + kFix4HashSize)[hv] = p->pos;
+        SKIP_FOOTER
+    }
+    while (--num != 0);
+}
+
+/*
+static void Bt5_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
+{
+  do
+  {
+    UInt32 h2, h3, h4;
+    UInt32 *hash;
+    SKIP_HEADER(5)
+    HASH5_CALC;
+    hash = p->hash;
+    curMatch = (hash + kFix5HashSize)[hv];
+    hash                  [h2] =
+    (hash + kFix3HashSize)[h3] =
+    (hash + kFix4HashSize)[h4] =
+    (hash + kFix5HashSize)[hv] = p->pos;
+    SKIP_FOOTER
+  }
+  while (--num != 0);
+}
+ */
+
+static void Hc4_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
+{
+    do
+    {
+        UInt32 h2, h3;
+        UInt32 *hash;
+        SKIP_HEADER(4)
+        HASH4_CALC;
+        hash = p->hash;
+        curMatch = (hash + kFix4HashSize)[hv];
+        hash [h2] =
+                (hash + kFix3HashSize)[h3] =
+                (hash + kFix4HashSize)[hv] = p->pos;
+        p->son[p->cyclicBufferPos] = curMatch;
+        MOVE_POS
+    }
+    while (--num != 0);
+}
+
+/*
+static void Hc5_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
+{
+  do
+  {
+    UInt32 h2, h3, h4;
+    UInt32 *hash;
+    SKIP_HEADER(5)
+    HASH5_CALC;
+    hash = p->hash;
+    curMatch = hash + kFix5HashSize)[hv];
+    hash                  [h2] =
+    (hash + kFix3HashSize)[h3] =
+    (hash + kFix4HashSize)[h4] =
+    (hash + kFix5HashSize)[hv] = p->pos;
+    p->son[p->cyclicBufferPos] = curMatch;
+    MOVE_POS
+  }
+  while (--num != 0);
+}
+ */
+
+void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
+{
+    do
+    {
+        SKIP_HEADER(3)
+        HASH_ZIP_CALC;
+        curMatch = p->hash[hv];
+        p->hash[hv] = p->pos;
+        p->son[p->cyclicBufferPos] = curMatch;
+        MOVE_POS
+    }
+    while (--num != 0);
+}
+
+void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable)
+{
+    vTable->Init = (Mf_Init_Func) MatchFinder_Init;
+    vTable->GetNumAvailableBytes = (Mf_GetNumAvailableBytes_Func) MatchFinder_GetNumAvailableBytes;
+    vTable->GetPointerToCurrentPos = (Mf_GetPointerToCurrentPos_Func) MatchFinder_GetPointerToCurrentPos;
+    if (!p->btMode)
+    {
+        /* if (p->numHashBytes <= 4) */
+        {
+            vTable->GetMatches = (Mf_GetMatches_Func) Hc4_MatchFinder_GetMatches;
+            vTable->Skip = (Mf_Skip_Func) Hc4_MatchFinder_Skip;
+        }
+        /*
+        else
+        {
+          vTable->GetMatches = (Mf_GetMatches_Func)Hc5_MatchFinder_GetMatches;
+          vTable->Skip = (Mf_Skip_Func)Hc5_MatchFinder_Skip;
+        }
+         */
+    }
+    else if (p->numHashBytes == 2)
+    {
+        vTable->GetMatches = (Mf_GetMatches_Func) Bt2_MatchFinder_GetMatches;
+        vTable->Skip = (Mf_Skip_Func) Bt2_MatchFinder_Skip;
+    }
+    else if (p->numHashBytes == 3)
+    {
+        vTable->GetMatches = (Mf_GetMatches_Func) Bt3_MatchFinder_GetMatches;
+        vTable->Skip = (Mf_Skip_Func) Bt3_MatchFinder_Skip;
+    }
+    else /* if (p->numHashBytes == 4) */
+    {
+        vTable->GetMatches = (Mf_GetMatches_Func) Bt4_MatchFinder_GetMatches;
+        vTable->Skip = (Mf_Skip_Func) Bt4_MatchFinder_Skip;
+    }
+    /*
+    else
+    {
+      vTable->GetMatches = (Mf_GetMatches_Func)Bt5_MatchFinder_GetMatches;
+      vTable->Skip = (Mf_Skip_Func)Bt5_MatchFinder_Skip;
+    }
+     */
+}

+ 121 - 0
src/master/user/lzma/LzFind.h

@@ -0,0 +1,121 @@
+/* LzFind.h -- Match finder for LZ algorithms
+2017-06-10 : Igor Pavlov : Public domain */
+
+#ifndef __LZ_FIND_H
+#define __LZ_FIND_H
+
+#include "7zTypes.h"
+
+EXTERN_C_BEGIN
+
+typedef UInt32 CLzRef;
+
+typedef struct _CMatchFinder
+{
+  Byte *buffer;
+  UInt32 pos;
+  UInt32 posLimit;
+  UInt32 streamPos;
+  UInt32 lenLimit;
+
+  UInt32 cyclicBufferPos;
+  UInt32 cyclicBufferSize; /* it must be = (historySize + 1) */
+
+  Byte streamEndWasReached;
+  Byte btMode;
+  Byte bigHash;
+  Byte directInput;
+
+  UInt32 matchMaxLen;
+  CLzRef *hash;
+  CLzRef *son;
+  UInt32 hashMask;
+  UInt32 cutValue;
+
+  Byte *bufferBase;
+  ISeqInStream *stream;
+  
+  UInt32 blockSize;
+  UInt32 keepSizeBefore;
+  UInt32 keepSizeAfter;
+
+  UInt32 numHashBytes;
+  size_t directInputRem;
+  UInt32 historySize;
+  UInt32 fixedHashSize;
+  UInt32 hashSizeSum;
+  SRes result;
+  UInt32 crc[256];
+  size_t numRefs;
+
+  UInt64 expectedDataSize;
+} CMatchFinder;
+
+#define Inline_MatchFinder_GetPointerToCurrentPos(p) ((p)->buffer)
+
+#define Inline_MatchFinder_GetNumAvailableBytes(p) ((p)->streamPos - (p)->pos)
+
+#define Inline_MatchFinder_IsFinishedOK(p) \
+    ((p)->streamEndWasReached \
+        && (p)->streamPos == (p)->pos \
+        && (!(p)->directInput || (p)->directInputRem == 0))
+      
+int MatchFinder_NeedMove(CMatchFinder *p);
+Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p);
+void MatchFinder_MoveBlock(CMatchFinder *p);
+void MatchFinder_ReadIfRequired(CMatchFinder *p);
+
+void MatchFinder_Construct(CMatchFinder *p);
+
+/* Conditions:
+     historySize <= 3 GB
+     keepAddBufferBefore + matchMaxLen + keepAddBufferAfter < 511MB
+*/
+int MatchFinder_Create(CMatchFinder *p, UInt32 historySize,
+    UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter,
+    ISzAllocPtr alloc);
+void MatchFinder_Free(CMatchFinder *p, ISzAllocPtr alloc);
+void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, size_t numItems);
+void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue);
+
+UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *buffer, CLzRef *son,
+    UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 _cutValue,
+    UInt32 *distances, UInt32 maxLen);
+
+/*
+Conditions:
+  Mf_GetNumAvailableBytes_Func must be called before each Mf_GetMatchLen_Func.
+  Mf_GetPointerToCurrentPos_Func's result must be used only before any other function
+*/
+
+typedef void (*Mf_Init_Func)(void *object);
+typedef UInt32 (*Mf_GetNumAvailableBytes_Func)(void *object);
+typedef const Byte * (*Mf_GetPointerToCurrentPos_Func)(void *object);
+typedef UInt32 (*Mf_GetMatches_Func)(void *object, UInt32 *distances);
+typedef void (*Mf_Skip_Func)(void *object, UInt32);
+
+typedef struct _IMatchFinder
+{
+  Mf_Init_Func Init;
+  Mf_GetNumAvailableBytes_Func GetNumAvailableBytes;
+  Mf_GetPointerToCurrentPos_Func GetPointerToCurrentPos;
+  Mf_GetMatches_Func GetMatches;
+  Mf_Skip_Func Skip;
+} IMatchFinder;
+
+void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable);
+
+void MatchFinder_Init_LowHash(CMatchFinder *p);
+void MatchFinder_Init_HighHash(CMatchFinder *p);
+void MatchFinder_Init_3(CMatchFinder *p, int readData);
+void MatchFinder_Init(CMatchFinder *p);
+
+UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances);
+UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances);
+
+void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num);
+void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num);
+
+EXTERN_C_END
+
+#endif

+ 57 - 0
src/master/user/lzma/LzHash.h

@@ -0,0 +1,57 @@
+/* LzHash.h -- HASH functions for LZ algorithms
+2015-04-12 : Igor Pavlov : Public domain */
+
+#ifndef __LZ_HASH_H
+#define __LZ_HASH_H
+
+#define kHash2Size (1 << 10)
+#define kHash3Size (1 << 16)
+#define kHash4Size (1 << 20)
+
+#define kFix3HashSize (kHash2Size)
+#define kFix4HashSize (kHash2Size + kHash3Size)
+#define kFix5HashSize (kHash2Size + kHash3Size + kHash4Size)
+
+#define HASH2_CALC hv = cur[0] | ((UInt32)cur[1] << 8);
+
+#define HASH3_CALC { \
+  UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
+  h2 = temp & (kHash2Size - 1); \
+  hv = (temp ^ ((UInt32)cur[2] << 8)) & p->hashMask; }
+
+#define HASH4_CALC { \
+  UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
+  h2 = temp & (kHash2Size - 1); \
+  temp ^= ((UInt32)cur[2] << 8); \
+  h3 = temp & (kHash3Size - 1); \
+  hv = (temp ^ (p->crc[cur[3]] << 5)) & p->hashMask; }
+
+#define HASH5_CALC { \
+  UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
+  h2 = temp & (kHash2Size - 1); \
+  temp ^= ((UInt32)cur[2] << 8); \
+  h3 = temp & (kHash3Size - 1); \
+  temp ^= (p->crc[cur[3]] << 5); \
+  h4 = temp & (kHash4Size - 1); \
+  hv = (temp ^ (p->crc[cur[4]] << 3)) & p->hashMask; }
+
+/* #define HASH_ZIP_CALC hv = ((cur[0] | ((UInt32)cur[1] << 8)) ^ p->crc[cur[2]]) & 0xFFFF; */
+#define HASH_ZIP_CALC hv = ((cur[2] | ((UInt32)cur[0] << 8)) ^ p->crc[cur[1]]) & 0xFFFF;
+
+
+#define MT_HASH2_CALC \
+  h2 = (p->crc[cur[0]] ^ cur[1]) & (kHash2Size - 1);
+
+#define MT_HASH3_CALC { \
+  UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
+  h2 = temp & (kHash2Size - 1); \
+  h3 = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); }
+
+#define MT_HASH4_CALC { \
+  UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
+  h2 = temp & (kHash2Size - 1); \
+  temp ^= ((UInt32)cur[2] << 8); \
+  h3 = temp & (kHash3Size - 1); \
+  h4 = (temp ^ (p->crc[cur[3]] << 5)) & (kHash4Size - 1); }
+
+#endif

+ 1209 - 0
src/master/user/lzma/LzmaDec.c

@@ -0,0 +1,1209 @@
+/* LzmaDec.c -- LZMA Decoder
+2018-07-04 : Igor Pavlov : Public domain */
+
+#include "Precomp.h"
+
+#include <string.h>
+
+/* #include "CpuArch.h" */
+#include "LzmaDec.h"
+
+#define kNumTopBits 24
+#define kTopValue ((UInt32)1 << kNumTopBits)
+
+#define kNumBitModelTotalBits 11
+#define kBitModelTotal (1 << kNumBitModelTotalBits)
+#define kNumMoveBits 5
+
+#define RC_INIT_SIZE 5
+
+#define NORMALIZE if (range < kTopValue) { range <<= 8; code = (code << 8) | (*buf++); }
+
+#define IF_BIT_0(p) ttt = *(p); NORMALIZE; bound = (range >> kNumBitModelTotalBits) * (UInt32)ttt; if (code < bound)
+#define UPDATE_0(p) range = bound; *(p) = (CLzmaProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits));
+#define UPDATE_1(p) range -= bound; code -= bound; *(p) = (CLzmaProb)(ttt - (ttt >> kNumMoveBits));
+#define GET_BIT2(p, i, A0, A1) IF_BIT_0(p) \
+  { UPDATE_0(p); i = (i + i); A0; } else \
+  { UPDATE_1(p); i = (i + i) + 1; A1; }
+
+#define TREE_GET_BIT(probs, i) { GET_BIT2(probs + i, i, ;, ;); }
+
+#define REV_BIT(p, i, A0, A1) IF_BIT_0(p + i) \
+  { UPDATE_0(p + i); A0; } else \
+  { UPDATE_1(p + i); A1; }
+#define REV_BIT_VAR(  p, i, m) REV_BIT(p, i, i += m; m += m, m += m; i += m; )
+#define REV_BIT_CONST(p, i, m) REV_BIT(p, i, i += m;       , i += m * 2; )
+#define REV_BIT_LAST( p, i, m) REV_BIT(p, i, i -= m        , ; )
+
+#define TREE_DECODE(probs, limit, i) \
+  { i = 1; do { TREE_GET_BIT(probs, i); } while (i < limit); i -= limit; }
+
+/* #define _LZMA_SIZE_OPT */
+
+#ifdef _LZMA_SIZE_OPT
+#define TREE_6_DECODE(probs, i) TREE_DECODE(probs, (1 << 6), i)
+#else
+#define TREE_6_DECODE(probs, i) \
+  { i = 1; \
+  TREE_GET_BIT(probs, i); \
+  TREE_GET_BIT(probs, i); \
+  TREE_GET_BIT(probs, i); \
+  TREE_GET_BIT(probs, i); \
+  TREE_GET_BIT(probs, i); \
+  TREE_GET_BIT(probs, i); \
+  i -= 0x40; }
+#endif
+
+#define NORMAL_LITER_DEC TREE_GET_BIT(prob, symbol)
+#define MATCHED_LITER_DEC \
+  matchByte += matchByte; \
+  bit = offs; \
+  offs &= matchByte; \
+  probLit = prob + (offs + bit + symbol); \
+  GET_BIT2(probLit, symbol, offs ^= bit; , ;)
+
+
+
+#define NORMALIZE_CHECK if (range < kTopValue) { if (buf >= bufLimit) return DUMMY_ERROR; range <<= 8; code = (code << 8) | (*buf++); }
+
+#define IF_BIT_0_CHECK(p) ttt = *(p); NORMALIZE_CHECK; bound = (range >> kNumBitModelTotalBits) * (UInt32)ttt; if (code < bound)
+#define UPDATE_0_CHECK range = bound;
+#define UPDATE_1_CHECK range -= bound; code -= bound;
+#define GET_BIT2_CHECK(p, i, A0, A1) IF_BIT_0_CHECK(p) \
+  { UPDATE_0_CHECK; i = (i + i); A0; } else \
+  { UPDATE_1_CHECK; i = (i + i) + 1; A1; }
+#define GET_BIT_CHECK(p, i) GET_BIT2_CHECK(p, i, ; , ;)
+#define TREE_DECODE_CHECK(probs, limit, i) \
+  { i = 1; do { GET_BIT_CHECK(probs + i, i) } while (i < limit); i -= limit; }
+
+
+#define REV_BIT_CHECK(p, i, m) IF_BIT_0_CHECK(p + i) \
+  { UPDATE_0_CHECK; i += m; m += m; } else \
+  { UPDATE_1_CHECK; m += m; i += m; }
+
+
+#define kNumPosBitsMax 4
+#define kNumPosStatesMax (1 << kNumPosBitsMax)
+
+#define kLenNumLowBits 3
+#define kLenNumLowSymbols (1 << kLenNumLowBits)
+#define kLenNumHighBits 8
+#define kLenNumHighSymbols (1 << kLenNumHighBits)
+
+#define LenLow 0
+#define LenHigh (LenLow + 2 * (kNumPosStatesMax << kLenNumLowBits))
+#define kNumLenProbs (LenHigh + kLenNumHighSymbols)
+
+#define LenChoice LenLow
+#define LenChoice2 (LenLow + (1 << kLenNumLowBits))
+
+#define kNumStates 12
+#define kNumStates2 16
+#define kNumLitStates 7
+
+#define kStartPosModelIndex 4
+#define kEndPosModelIndex 14
+#define kNumFullDistances (1 << (kEndPosModelIndex >> 1))
+
+#define kNumPosSlotBits 6
+#define kNumLenToPosStates 4
+
+#define kNumAlignBits 4
+#define kAlignTableSize (1 << kNumAlignBits)
+
+#define kMatchMinLen 2
+#define kMatchSpecLenStart (kMatchMinLen + kLenNumLowSymbols * 2 + kLenNumHighSymbols)
+
+/* External ASM code needs same CLzmaProb array layout. So don't change it. */
+
+/* (probs_1664) is faster and better for code size at some platforms */
+/*
+#ifdef MY_CPU_X86_OR_AMD64
+ */
+#define kStartOffset 1664
+#define GET_PROBS p->probs_1664
+/*
+#define GET_PROBS p->probs + kStartOffset
+#else
+#define kStartOffset 0
+#define GET_PROBS p->probs
+#endif
+ */
+
+#define SpecPos (-kStartOffset)
+#define IsRep0Long (SpecPos + kNumFullDistances)
+#define RepLenCoder (IsRep0Long + (kNumStates2 << kNumPosBitsMax))
+#define LenCoder (RepLenCoder + kNumLenProbs)
+#define IsMatch (LenCoder + kNumLenProbs)
+#define Align (IsMatch + (kNumStates2 << kNumPosBitsMax))
+#define IsRep (Align + kAlignTableSize)
+#define IsRepG0 (IsRep + kNumStates)
+#define IsRepG1 (IsRepG0 + kNumStates)
+#define IsRepG2 (IsRepG1 + kNumStates)
+#define PosSlot (IsRepG2 + kNumStates)
+#define Literal (PosSlot + (kNumLenToPosStates << kNumPosSlotBits))
+#define NUM_BASE_PROBS (Literal + kStartOffset)
+
+#if Align != 0 && kStartOffset != 0
+#error Stop_Compiling_Bad_LZMA_kAlign
+#endif
+
+#if NUM_BASE_PROBS != 1984
+#error Stop_Compiling_Bad_LZMA_PROBS
+#endif
+
+
+#define LZMA_LIT_SIZE 0x300
+
+#define LzmaProps_GetNumProbs(p) (NUM_BASE_PROBS + ((UInt32)LZMA_LIT_SIZE << ((p)->lc + (p)->lp)))
+
+
+#define CALC_POS_STATE(processedPos, pbMask) (((processedPos) & (pbMask)) << 4)
+#define COMBINED_PS_STATE (posState + state)
+#define GET_LEN_STATE (posState)
+
+#define LZMA_DIC_MIN (1 << 12)
+
+/*
+p->remainLen : shows status of LZMA decoder:
+    < kMatchSpecLenStart : normal remain
+    = kMatchSpecLenStart : finished
+    = kMatchSpecLenStart + 1 : need init range coder
+    = kMatchSpecLenStart + 2 : need init range coder and state
+ */
+
+/* ---------- LZMA_DECODE_REAL ---------- */
+/*
+LzmaDec_DecodeReal_3() can be implemented in external ASM file.
+3 - is the code compatibility version of that function for check at link time.
+ */
+
+#define LZMA_DECODE_REAL LzmaDec_DecodeReal_3
+
+/*
+LZMA_DECODE_REAL()
+In:
+  RangeCoder is normalized
+  if (p->dicPos == limit)
+  {
+    LzmaDec_TryDummy() was called before to exclude LITERAL and MATCH-REP cases.
+    So first symbol can be only MATCH-NON-REP. And if that MATCH-NON-REP symbol
+    is not END_OF_PAYALOAD_MARKER, then function returns error code.
+  }
+
+Processing:
+  first LZMA symbol will be decoded in any case
+  All checks for limits are at the end of main loop,
+  It will decode new LZMA-symbols while (p->buf < bufLimit && dicPos < limit),
+  RangeCoder is still without last normalization when (p->buf < bufLimit) is being checked.
+
+Out:
+  RangeCoder is normalized
+  Result:
+    SZ_OK - OK
+    SZ_ERROR_DATA - Error
+  p->remainLen:
+    < kMatchSpecLenStart : normal remain
+    = kMatchSpecLenStart : finished
+ */
+
+
+#ifdef _LZMA_DEC_OPT
+
+int MY_FAST_CALL LZMA_DECODE_REAL(CLzmaDec *p, SizeT limit, const Byte *bufLimit);
+
+#else
+
+static
+int MY_FAST_CALL LZMA_DECODE_REAL(CLzmaDec *p, SizeT limit, const Byte *bufLimit)
+{
+    CLzmaProb *probs = GET_PROBS;
+    unsigned state = (unsigned) p->state;
+    UInt32 rep0 = p->reps[0], rep1 = p->reps[1], rep2 = p->reps[2], rep3 = p->reps[3];
+    unsigned pbMask = ((unsigned) 1 << (p->prop.pb)) - 1;
+    unsigned lc = p->prop.lc;
+    unsigned lpMask = ((unsigned) 0x100 << p->prop.lp) - ((unsigned) 0x100 >> lc);
+
+    Byte *dic = p->dic;
+    SizeT dicBufSize = p->dicBufSize;
+    SizeT dicPos = p->dicPos;
+
+    UInt32 processedPos = p->processedPos;
+    UInt32 checkDicSize = p->checkDicSize;
+    unsigned len = 0;
+
+    const Byte *buf = p->buf;
+    UInt32 range = p->range;
+    UInt32 code = p->code;
+
+    do
+    {
+        CLzmaProb *prob;
+        UInt32 bound;
+        unsigned ttt;
+        unsigned posState = CALC_POS_STATE(processedPos, pbMask);
+
+        prob = probs + IsMatch + COMBINED_PS_STATE;
+
+        IF_BIT_0(prob)
+        {
+            unsigned symbol;
+            UPDATE_0(prob);
+            prob = probs + Literal;
+            if (processedPos != 0 || checkDicSize != 0)
+                prob += (UInt32) 3 * ((((processedPos << 8) + dic[(dicPos == 0 ? dicBufSize : dicPos) - 1]) & lpMask) << lc);
+            processedPos++;
+
+            if (state < kNumLitStates)
+            {
+                state -= (state < 4) ? state : 3;
+                symbol = 1;
+#ifdef _LZMA_SIZE_OPT
+                do
+                {
+                    NORMAL_LITER_DEC
+                }
+                while (symbol < 0x100);
+#else
+                NORMAL_LITER_DEC
+                NORMAL_LITER_DEC
+                NORMAL_LITER_DEC
+                NORMAL_LITER_DEC
+                NORMAL_LITER_DEC
+                NORMAL_LITER_DEC
+                NORMAL_LITER_DEC
+                NORMAL_LITER_DEC
+#endif
+            }
+            else
+            {
+                unsigned matchByte = dic[dicPos - rep0 + (dicPos < rep0 ? dicBufSize : 0)];
+                unsigned offs = 0x100;
+                state -= (state < 10) ? 3 : 6;
+                symbol = 1;
+#ifdef _LZMA_SIZE_OPT
+                do
+                {
+                    unsigned bit;
+                    CLzmaProb *probLit;
+                    MATCHED_LITER_DEC
+                }
+                while (symbol < 0x100);
+#else
+                {
+                    unsigned bit;
+                    CLzmaProb *probLit;
+                    MATCHED_LITER_DEC
+                    MATCHED_LITER_DEC
+                    MATCHED_LITER_DEC
+                    MATCHED_LITER_DEC
+                    MATCHED_LITER_DEC
+                    MATCHED_LITER_DEC
+                    MATCHED_LITER_DEC
+                    MATCHED_LITER_DEC
+                }
+#endif
+            }
+
+            dic[dicPos++] = (Byte) symbol;
+            continue;
+        }
+
+        {
+            UPDATE_1(prob);
+            prob = probs + IsRep + state;
+
+            IF_BIT_0(prob)
+            {
+                UPDATE_0(prob);
+                state += kNumStates;
+                prob = probs + LenCoder;
+            }
+            else
+            {
+                UPDATE_1(prob);
+                /*
+                // that case was checked before with kBadRepCode
+                if (checkDicSize == 0 && processedPos == 0)
+                  return SZ_ERROR_DATA;
+                 */
+                prob = probs + IsRepG0 + state;
+
+                IF_BIT_0(prob)
+                {
+                    UPDATE_0(prob);
+                    prob = probs + IsRep0Long + COMBINED_PS_STATE;
+
+                    IF_BIT_0(prob)
+                    {
+                        UPDATE_0(prob);
+                        dic[dicPos] = dic[dicPos - rep0 + (dicPos < rep0 ? dicBufSize : 0)];
+                        dicPos++;
+                        processedPos++;
+                        state = state < kNumLitStates ? 9 : 11;
+                        continue;
+                    }
+                    UPDATE_1(prob);
+                }
+                else
+                {
+                    UInt32 distance;
+                    UPDATE_1(prob);
+                    prob = probs + IsRepG1 + state;
+
+                    IF_BIT_0(prob)
+                    {
+                        UPDATE_0(prob);
+                        distance = rep1;
+                    }
+                    else
+                    {
+                        UPDATE_1(prob);
+                        prob = probs + IsRepG2 + state;
+
+                        IF_BIT_0(prob)
+                        {
+                            UPDATE_0(prob);
+                            distance = rep2;
+                        }
+                        else
+                        {
+                            UPDATE_1(prob);
+                            distance = rep3;
+                            rep3 = rep2;
+                        }
+                        rep2 = rep1;
+                    }
+                    rep1 = rep0;
+                    rep0 = distance;
+                }
+                state = state < kNumLitStates ? 8 : 11;
+                prob = probs + RepLenCoder;
+            }
+
+#ifdef _LZMA_SIZE_OPT
+            {
+                unsigned lim, offset;
+                CLzmaProb *probLen = prob + LenChoice;
+
+                IF_BIT_0(probLen)
+                {
+                    UPDATE_0(probLen);
+                    probLen = prob + LenLow + GET_LEN_STATE;
+                    offset = 0;
+                    lim = (1 << kLenNumLowBits);
+                }
+                else
+                {
+                    UPDATE_1(probLen);
+                    probLen = prob + LenChoice2;
+
+                    IF_BIT_0(probLen)
+                    {
+                        UPDATE_0(probLen);
+                        probLen = prob + LenLow + GET_LEN_STATE + (1 << kLenNumLowBits);
+                        offset = kLenNumLowSymbols;
+                        lim = (1 << kLenNumLowBits);
+                    }
+                    else
+                    {
+                        UPDATE_1(probLen);
+                        probLen = prob + LenHigh;
+                        offset = kLenNumLowSymbols * 2;
+                        lim = (1 << kLenNumHighBits);
+                    }
+                }
+                TREE_DECODE(probLen, lim, len);
+                len += offset;
+            }
+#else
+            {
+                CLzmaProb *probLen = prob + LenChoice;
+
+                IF_BIT_0(probLen)
+                {
+                    UPDATE_0(probLen);
+                    probLen = prob + LenLow + GET_LEN_STATE;
+                    len = 1;
+                    TREE_GET_BIT(probLen, len);
+                    TREE_GET_BIT(probLen, len);
+                    TREE_GET_BIT(probLen, len);
+                    len -= 8;
+                }
+                else
+                {
+                    UPDATE_1(probLen);
+                    probLen = prob + LenChoice2;
+
+                    IF_BIT_0(probLen)
+                    {
+                        UPDATE_0(probLen);
+                        probLen = prob + LenLow + GET_LEN_STATE + (1 << kLenNumLowBits);
+                        len = 1;
+                        TREE_GET_BIT(probLen, len);
+                        TREE_GET_BIT(probLen, len);
+                        TREE_GET_BIT(probLen, len);
+                    }
+                    else
+                    {
+                        UPDATE_1(probLen);
+                        probLen = prob + LenHigh;
+                        TREE_DECODE(probLen, (1 << kLenNumHighBits), len);
+                        len += kLenNumLowSymbols * 2;
+                    }
+                }
+            }
+#endif
+
+            if (state >= kNumStates)
+            {
+                UInt32 distance;
+                prob = probs + PosSlot +
+                        ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << kNumPosSlotBits);
+                TREE_6_DECODE(prob, distance);
+                if (distance >= kStartPosModelIndex)
+                {
+                    unsigned posSlot = (unsigned) distance;
+                    unsigned numDirectBits = (unsigned) (((distance >> 1) - 1));
+                    distance = (2 | (distance & 1));
+                    if (posSlot < kEndPosModelIndex)
+                    {
+                        distance <<= numDirectBits;
+                        prob = probs + SpecPos;
+                        {
+                            UInt32 m = 1;
+                            distance++;
+                            do
+                            {
+                                REV_BIT_VAR(prob, distance, m);
+                            }
+                            while (--numDirectBits);
+                            distance -= m;
+                        }
+                    }
+                    else
+                    {
+                        numDirectBits -= kNumAlignBits;
+                        do
+                        {
+                            NORMALIZE
+                            range >>= 1;
+
+                            {
+                                UInt32 t;
+                                code -= range;
+                                t = (0 - ((UInt32) code >> 31)); /* (UInt32)((Int32)code >> 31) */
+                                distance = (distance << 1) + (t + 1);
+                                code += range & t;
+                            }
+                            /*
+                            distance <<= 1;
+                            if (code >= range)
+                            {
+                              code -= range;
+                              distance |= 1;
+                            }
+                             */
+                        }
+                        while (--numDirectBits);
+                        prob = probs + Align;
+                        distance <<= kNumAlignBits;
+                        {
+                            unsigned i = 1;
+                            REV_BIT_CONST(prob, i, 1);
+                            REV_BIT_CONST(prob, i, 2);
+                            REV_BIT_CONST(prob, i, 4);
+                            REV_BIT_LAST(prob, i, 8);
+                            distance |= i;
+                        }
+                        if (distance == (UInt32) 0xFFFFFFFF)
+                        {
+                            len = kMatchSpecLenStart;
+                            state -= kNumStates;
+                            break;
+                        }
+                    }
+                }
+
+                rep3 = rep2;
+                rep2 = rep1;
+                rep1 = rep0;
+                rep0 = distance + 1;
+                state = (state < kNumStates + kNumLitStates) ? kNumLitStates : kNumLitStates + 3;
+                if (distance >= (checkDicSize == 0 ? processedPos : checkDicSize))
+                {
+                    p->dicPos = dicPos;
+                    return SZ_ERROR_DATA;
+                }
+            }
+
+            len += kMatchMinLen;
+
+            {
+                SizeT rem;
+                unsigned curLen;
+                SizeT pos;
+
+                if ((rem = limit - dicPos) == 0)
+                {
+                    p->dicPos = dicPos;
+                    return SZ_ERROR_DATA;
+                }
+
+                curLen = ((rem < len) ? (unsigned) rem : len);
+                pos = dicPos - rep0 + (dicPos < rep0 ? dicBufSize : 0);
+
+                processedPos += (UInt32) curLen;
+
+                len -= curLen;
+                if (curLen <= dicBufSize - pos)
+                {
+                    Byte *dest = dic + dicPos;
+                    ptrdiff_t src = (ptrdiff_t) pos - (ptrdiff_t) dicPos;
+                    const Byte *lim = dest + curLen;
+                    dicPos += (SizeT) curLen;
+                    do
+                        *(dest) = (Byte)*(dest + src);
+                    while (++dest != lim);
+                }
+                else
+                {
+                    do
+                    {
+                        dic[dicPos++] = dic[pos];
+                        if (++pos == dicBufSize)
+                            pos = 0;
+                    }
+                    while (--curLen != 0);
+                }
+            }
+        }
+    }
+    while (dicPos < limit && buf < bufLimit);
+
+    NORMALIZE;
+
+    p->buf = buf;
+    p->range = range;
+    p->code = code;
+    p->remainLen = (UInt32) len;
+    p->dicPos = dicPos;
+    p->processedPos = processedPos;
+    p->reps[0] = rep0;
+    p->reps[1] = rep1;
+    p->reps[2] = rep2;
+    p->reps[3] = rep3;
+    p->state = (UInt32) state;
+
+    return SZ_OK;
+}
+#endif
+
+static void MY_FAST_CALL LzmaDec_WriteRem(CLzmaDec *p, SizeT limit)
+{
+    if (p->remainLen != 0 && p->remainLen < kMatchSpecLenStart)
+    {
+        Byte *dic = p->dic;
+        SizeT dicPos = p->dicPos;
+        SizeT dicBufSize = p->dicBufSize;
+        unsigned len = (unsigned) p->remainLen;
+        SizeT rep0 = p->reps[0]; /* we use SizeT to avoid the BUG of VC14 for AMD64 */
+        SizeT rem = limit - dicPos;
+        if (rem < len)
+            len = (unsigned) (rem);
+
+        if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= len)
+            p->checkDicSize = p->prop.dicSize;
+
+        p->processedPos += (UInt32) len;
+        p->remainLen -= (UInt32) len;
+        while (len != 0)
+        {
+            len--;
+            dic[dicPos] = dic[dicPos - rep0 + (dicPos < rep0 ? dicBufSize : 0)];
+            dicPos++;
+        }
+        p->dicPos = dicPos;
+    }
+}
+
+
+#define kRange0 0xFFFFFFFF
+#define kBound0 ((kRange0 >> kNumBitModelTotalBits) << (kNumBitModelTotalBits - 1))
+#define kBadRepCode (kBound0 + (((kRange0 - kBound0) >> kNumBitModelTotalBits) << (kNumBitModelTotalBits - 1)))
+#if kBadRepCode != (0xC0000000 - 0x400)
+#error Stop_Compiling_Bad_LZMA_Check
+#endif
+
+static int MY_FAST_CALL LzmaDec_DecodeReal2(CLzmaDec *p, SizeT limit, const Byte *bufLimit)
+{
+    do
+    {
+        SizeT limit2 = limit;
+        if (p->checkDicSize == 0)
+        {
+            UInt32 rem = p->prop.dicSize - p->processedPos;
+            if (limit - p->dicPos > rem)
+                limit2 = p->dicPos + rem;
+
+            if (p->processedPos == 0)
+                if (p->code >= kBadRepCode)
+                    return SZ_ERROR_DATA;
+        }
+
+        RINOK(LZMA_DECODE_REAL(p, limit2, bufLimit));
+
+        if (p->checkDicSize == 0 && p->processedPos >= p->prop.dicSize)
+            p->checkDicSize = p->prop.dicSize;
+
+        LzmaDec_WriteRem(p, limit);
+    }
+    while (p->dicPos < limit && p->buf < bufLimit && p->remainLen < kMatchSpecLenStart);
+
+    return 0;
+}
+
+typedef enum
+{
+    DUMMY_ERROR, /* unexpected end of input stream */
+    DUMMY_LIT,
+    DUMMY_MATCH,
+    DUMMY_REP
+} ELzmaDummy;
+
+static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inSize)
+{
+    UInt32 range = p->range;
+    UInt32 code = p->code;
+    const Byte *bufLimit = buf + inSize;
+    const CLzmaProb *probs = GET_PROBS;
+    unsigned state = (unsigned) p->state;
+    ELzmaDummy res;
+
+    {
+        const CLzmaProb *prob;
+        UInt32 bound;
+        unsigned ttt;
+        unsigned posState = CALC_POS_STATE(p->processedPos, (1 << p->prop.pb) - 1);
+
+        prob = probs + IsMatch + COMBINED_PS_STATE;
+
+        IF_BIT_0_CHECK(prob)
+        {
+            UPDATE_0_CHECK
+
+            /* if (bufLimit - buf >= 7) return DUMMY_LIT; */
+
+            prob = probs + Literal;
+            if (p->checkDicSize != 0 || p->processedPos != 0)
+                prob += ((UInt32) LZMA_LIT_SIZE *
+                    ((((p->processedPos) & ((1 << (p->prop.lp)) - 1)) << p->prop.lc) +
+                    (p->dic[(p->dicPos == 0 ? p->dicBufSize : p->dicPos) - 1] >> (8 - p->prop.lc))));
+
+            if (state < kNumLitStates)
+            {
+                unsigned symbol = 1;
+                do
+                {
+                    GET_BIT_CHECK(prob + symbol, symbol)
+                }
+                while (symbol < 0x100);
+            }
+            else
+            {
+                unsigned matchByte = p->dic[p->dicPos - p->reps[0] +
+                        (p->dicPos < p->reps[0] ? p->dicBufSize : 0)];
+                unsigned offs = 0x100;
+                unsigned symbol = 1;
+                do
+                {
+                    unsigned bit;
+                    const CLzmaProb *probLit;
+                    matchByte += matchByte;
+                    bit = offs;
+                    offs &= matchByte;
+                    probLit = prob + (offs + bit + symbol);
+                    GET_BIT2_CHECK(probLit, symbol, offs ^= bit;,;)
+                }
+                while (symbol < 0x100);
+            }
+            res = DUMMY_LIT;
+        }
+        else
+        {
+            unsigned len;
+            UPDATE_1_CHECK;
+
+            prob = probs + IsRep + state;
+
+            IF_BIT_0_CHECK(prob)
+            {
+                UPDATE_0_CHECK;
+                state = 0;
+                prob = probs + LenCoder;
+                res = DUMMY_MATCH;
+            }
+            else
+            {
+                UPDATE_1_CHECK;
+                res = DUMMY_REP;
+                prob = probs + IsRepG0 + state;
+
+                IF_BIT_0_CHECK(prob)
+                {
+                    UPDATE_0_CHECK;
+                    prob = probs + IsRep0Long + COMBINED_PS_STATE;
+
+                    IF_BIT_0_CHECK(prob)
+                    {
+                        UPDATE_0_CHECK;
+                        NORMALIZE_CHECK;
+                        return DUMMY_REP;
+                    }
+                    else
+                    {
+                        UPDATE_1_CHECK;
+                    }
+                }
+                else
+                {
+                    UPDATE_1_CHECK;
+                    prob = probs + IsRepG1 + state;
+
+                    IF_BIT_0_CHECK(prob)
+                    {
+                        UPDATE_0_CHECK;
+                    }
+                    else
+                    {
+                        UPDATE_1_CHECK;
+                        prob = probs + IsRepG2 + state;
+
+                        IF_BIT_0_CHECK(prob)
+                        {
+                            UPDATE_0_CHECK;
+                        }
+                        else
+                        {
+                            UPDATE_1_CHECK;
+                        }
+                    }
+                }
+                state = kNumStates;
+                prob = probs + RepLenCoder;
+            }
+            {
+                unsigned limit, offset;
+                const CLzmaProb *probLen = prob + LenChoice;
+
+                IF_BIT_0_CHECK(probLen)
+                {
+                    UPDATE_0_CHECK;
+                    probLen = prob + LenLow + GET_LEN_STATE;
+                    offset = 0;
+                    limit = 1 << kLenNumLowBits;
+                }
+                else
+                {
+                    UPDATE_1_CHECK;
+                    probLen = prob + LenChoice2;
+
+                    IF_BIT_0_CHECK(probLen)
+                    {
+                        UPDATE_0_CHECK;
+                        probLen = prob + LenLow + GET_LEN_STATE + (1 << kLenNumLowBits);
+                        offset = kLenNumLowSymbols;
+                        limit = 1 << kLenNumLowBits;
+                    }
+                    else
+                    {
+                        UPDATE_1_CHECK;
+                        probLen = prob + LenHigh;
+                        offset = kLenNumLowSymbols * 2;
+                        limit = 1 << kLenNumHighBits;
+                    }
+                }
+                TREE_DECODE_CHECK(probLen, limit, len);
+                len += offset;
+            }
+
+            if (state < 4)
+            {
+                unsigned posSlot;
+                prob = probs + PosSlot +
+                        ((len < kNumLenToPosStates - 1 ? len : kNumLenToPosStates - 1) <<
+                        kNumPosSlotBits);
+                TREE_DECODE_CHECK(prob, 1 << kNumPosSlotBits, posSlot);
+                if (posSlot >= kStartPosModelIndex)
+                {
+                    unsigned numDirectBits = ((posSlot >> 1) - 1);
+
+                    /* if (bufLimit - buf >= 8) return DUMMY_MATCH; */
+
+                    if (posSlot < kEndPosModelIndex)
+                    {
+                        prob = probs + SpecPos + ((2 | (posSlot & 1)) << numDirectBits);
+                    }
+                    else
+                    {
+                        numDirectBits -= kNumAlignBits;
+                        do
+                        {
+                            NORMALIZE_CHECK
+                            range >>= 1;
+                            code -= range & (((code - range) >> 31) - 1);
+                            /* if (code >= range) code -= range; */
+                        }
+                        while (--numDirectBits);
+                        prob = probs + Align;
+                        numDirectBits = kNumAlignBits;
+                    }
+                    {
+                        unsigned i = 1;
+                        unsigned m = 1;
+                        do
+                        {
+                            REV_BIT_CHECK(prob, i, m);
+                        }
+                        while (--numDirectBits);
+                    }
+                }
+            }
+        }
+    }
+    NORMALIZE_CHECK;
+    return res;
+}
+
+void LzmaDec_InitDicAndState(CLzmaDec *p, BoolInt initDic, BoolInt initState)
+{
+    p->remainLen = kMatchSpecLenStart + 1;
+    p->tempBufSize = 0;
+
+    if (initDic)
+    {
+        p->processedPos = 0;
+        p->checkDicSize = 0;
+        p->remainLen = kMatchSpecLenStart + 2;
+    }
+    if (initState)
+        p->remainLen = kMatchSpecLenStart + 2;
+}
+
+void LzmaDec_Init(CLzmaDec *p)
+{
+    p->dicPos = 0;
+    LzmaDec_InitDicAndState(p, True, True);
+}
+
+SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *srcLen,
+                         ELzmaFinishMode finishMode, ELzmaStatus *status)
+{
+    SizeT inSize = *srcLen;
+    (*srcLen) = 0;
+
+    *status = LZMA_STATUS_NOT_SPECIFIED;
+
+    if (p->remainLen > kMatchSpecLenStart)
+    {
+        for (; inSize > 0 && p->tempBufSize < RC_INIT_SIZE; (*srcLen)++, inSize--)
+            p->tempBuf[p->tempBufSize++] = *src++;
+        if (p->tempBufSize != 0 && p->tempBuf[0] != 0)
+            return SZ_ERROR_DATA;
+        if (p->tempBufSize < RC_INIT_SIZE)
+        {
+            *status = LZMA_STATUS_NEEDS_MORE_INPUT;
+            return SZ_OK;
+        }
+        p->code =
+                ((UInt32) p->tempBuf[1] << 24)
+                | ((UInt32) p->tempBuf[2] << 16)
+                | ((UInt32) p->tempBuf[3] << 8)
+                | ((UInt32) p->tempBuf[4]);
+        p->range = 0xFFFFFFFF;
+        p->tempBufSize = 0;
+
+        if (p->remainLen > kMatchSpecLenStart + 1)
+        {
+            SizeT numProbs = LzmaProps_GetNumProbs(&p->prop);
+            SizeT i;
+            CLzmaProb *probs = p->probs;
+            for (i = 0; i < numProbs; i++)
+                probs[i] = kBitModelTotal >> 1;
+            p->reps[0] = p->reps[1] = p->reps[2] = p->reps[3] = 1;
+            p->state = 0;
+        }
+
+        p->remainLen = 0;
+    }
+
+    LzmaDec_WriteRem(p, dicLimit);
+
+    while (p->remainLen != kMatchSpecLenStart)
+    {
+        int checkEndMarkNow = 0;
+
+        if (p->dicPos >= dicLimit)
+        {
+            if (p->remainLen == 0 && p->code == 0)
+            {
+                *status = LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK;
+                return SZ_OK;
+            }
+            if (finishMode == LZMA_FINISH_ANY)
+            {
+                *status = LZMA_STATUS_NOT_FINISHED;
+                return SZ_OK;
+            }
+            if (p->remainLen != 0)
+            {
+                *status = LZMA_STATUS_NOT_FINISHED;
+                return SZ_ERROR_DATA;
+            }
+            checkEndMarkNow = 1;
+        }
+
+        if (p->tempBufSize == 0)
+        {
+            SizeT processed;
+            const Byte *bufLimit;
+            if (inSize < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow)
+            {
+                int dummyRes = LzmaDec_TryDummy(p, src, inSize);
+                if (dummyRes == DUMMY_ERROR)
+                {
+                    memcpy(p->tempBuf, src, inSize);
+                    p->tempBufSize = (unsigned) inSize;
+                    (*srcLen) += inSize;
+                    *status = LZMA_STATUS_NEEDS_MORE_INPUT;
+                    return SZ_OK;
+                }
+                if (checkEndMarkNow && dummyRes != DUMMY_MATCH)
+                {
+                    *status = LZMA_STATUS_NOT_FINISHED;
+                    return SZ_ERROR_DATA;
+                }
+                bufLimit = src;
+            }
+            else
+                bufLimit = src + inSize - LZMA_REQUIRED_INPUT_MAX;
+            p->buf = src;
+            if (LzmaDec_DecodeReal2(p, dicLimit, bufLimit) != 0)
+                return SZ_ERROR_DATA;
+            processed = (SizeT) (p->buf - src);
+            (*srcLen) += processed;
+            src += processed;
+            inSize -= processed;
+        }
+        else
+        {
+            unsigned rem = p->tempBufSize, lookAhead = 0;
+            while (rem < LZMA_REQUIRED_INPUT_MAX && lookAhead < inSize)
+                p->tempBuf[rem++] = src[lookAhead++];
+            p->tempBufSize = rem;
+            if (rem < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow)
+            {
+                int dummyRes = LzmaDec_TryDummy(p, p->tempBuf, (SizeT) rem);
+                if (dummyRes == DUMMY_ERROR)
+                {
+                    (*srcLen) += (SizeT) lookAhead;
+                    *status = LZMA_STATUS_NEEDS_MORE_INPUT;
+                    return SZ_OK;
+                }
+                if (checkEndMarkNow && dummyRes != DUMMY_MATCH)
+                {
+                    *status = LZMA_STATUS_NOT_FINISHED;
+                    return SZ_ERROR_DATA;
+                }
+            }
+            p->buf = p->tempBuf;
+            if (LzmaDec_DecodeReal2(p, dicLimit, p->buf) != 0)
+                return SZ_ERROR_DATA;
+
+            {
+                unsigned kkk = (unsigned) (p->buf - p->tempBuf);
+                if (rem < kkk)
+                    return SZ_ERROR_FAIL; /* some internal error */
+                rem -= kkk;
+                if (lookAhead < rem)
+                    return SZ_ERROR_FAIL; /* some internal error */
+                lookAhead -= rem;
+            }
+            (*srcLen) += (SizeT) lookAhead;
+            src += lookAhead;
+            inSize -= (SizeT) lookAhead;
+            p->tempBufSize = 0;
+        }
+    }
+
+    if (p->code != 0)
+        return SZ_ERROR_DATA;
+    *status = LZMA_STATUS_FINISHED_WITH_MARK;
+    return SZ_OK;
+}
+
+SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)
+{
+    SizeT outSize = *destLen;
+    SizeT inSize = *srcLen;
+    *srcLen = *destLen = 0;
+    for (;;)
+    {
+        SizeT inSizeCur = inSize, outSizeCur, dicPos;
+        ELzmaFinishMode curFinishMode;
+        SRes res;
+        if (p->dicPos == p->dicBufSize)
+            p->dicPos = 0;
+        dicPos = p->dicPos;
+        if (outSize > p->dicBufSize - dicPos)
+        {
+            outSizeCur = p->dicBufSize;
+            curFinishMode = LZMA_FINISH_ANY;
+        }
+        else
+        {
+            outSizeCur = dicPos + outSize;
+            curFinishMode = finishMode;
+        }
+
+        res = LzmaDec_DecodeToDic(p, outSizeCur, src, &inSizeCur, curFinishMode, status);
+        src += inSizeCur;
+        inSize -= inSizeCur;
+        *srcLen += inSizeCur;
+        outSizeCur = p->dicPos - dicPos;
+        memcpy(dest, p->dic + dicPos, outSizeCur);
+        dest += outSizeCur;
+        outSize -= outSizeCur;
+        *destLen += outSizeCur;
+        if (res != 0)
+            return res;
+        if (outSizeCur == 0 || outSize == 0)
+            return SZ_OK;
+    }
+}
+
+void LzmaDec_FreeProbs(CLzmaDec *p, ISzAllocPtr alloc)
+{
+    ISzAlloc_Free(alloc, p->probs);
+    p->probs = NULL;
+}
+
+static void LzmaDec_FreeDict(CLzmaDec *p, ISzAllocPtr alloc)
+{
+    ISzAlloc_Free(alloc, p->dic);
+    p->dic = NULL;
+}
+
+void LzmaDec_Free(CLzmaDec *p, ISzAllocPtr alloc)
+{
+    LzmaDec_FreeProbs(p, alloc);
+    LzmaDec_FreeDict(p, alloc);
+}
+
+SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size)
+{
+    UInt32 dicSize;
+    Byte d;
+
+    if (size < LZMA_PROPS_SIZE)
+        return SZ_ERROR_UNSUPPORTED;
+    else
+        dicSize = data[1] | ((UInt32) data[2] << 8) | ((UInt32) data[3] << 16) | ((UInt32) data[4] << 24);
+
+    if (dicSize < LZMA_DIC_MIN)
+        dicSize = LZMA_DIC_MIN;
+    p->dicSize = dicSize;
+
+    d = data[0];
+    if (d >= (9 * 5 * 5))
+        return SZ_ERROR_UNSUPPORTED;
+
+    p->lc = (Byte) (d % 9);
+    d /= 9;
+    p->pb = (Byte) (d / 5);
+    p->lp = (Byte) (d % 5);
+
+    return SZ_OK;
+}
+
+static SRes LzmaDec_AllocateProbs2(CLzmaDec *p, const CLzmaProps *propNew, ISzAllocPtr alloc)
+{
+    UInt32 numProbs = LzmaProps_GetNumProbs(propNew);
+    if (!p->probs || numProbs != p->numProbs)
+    {
+        LzmaDec_FreeProbs(p, alloc);
+        p->probs = (CLzmaProb *) ISzAlloc_Alloc(alloc, numProbs * sizeof (CLzmaProb));
+        if (!p->probs)
+            return SZ_ERROR_MEM;
+        p->probs_1664 = p->probs + 1664;
+        p->numProbs = numProbs;
+    }
+    return SZ_OK;
+}
+
+SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAllocPtr alloc)
+{
+    CLzmaProps propNew;
+    RINOK(LzmaProps_Decode(&propNew, props, propsSize));
+    RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc));
+    p->prop = propNew;
+    return SZ_OK;
+}
+
+SRes LzmaDec_Allocate(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAllocPtr alloc)
+{
+    CLzmaProps propNew;
+    SizeT dicBufSize;
+    RINOK(LzmaProps_Decode(&propNew, props, propsSize));
+    RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc));
+
+    {
+        UInt32 dictSize = propNew.dicSize;
+        SizeT mask = ((UInt32) 1 << 12) - 1;
+        if (dictSize >= ((UInt32) 1 << 30)) mask = ((UInt32) 1 << 22) - 1;
+        else if (dictSize >= ((UInt32) 1 << 22)) mask = ((UInt32) 1 << 20) - 1;
+        ;
+        dicBufSize = ((SizeT) dictSize + mask) & ~mask;
+        if (dicBufSize < dictSize)
+            dicBufSize = dictSize;
+    }
+
+    if (!p->dic || dicBufSize != p->dicBufSize)
+    {
+        LzmaDec_FreeDict(p, alloc);
+        p->dic = (Byte *) ISzAlloc_Alloc(alloc, dicBufSize);
+        if (!p->dic)
+        {
+            LzmaDec_FreeProbs(p, alloc);
+            return SZ_ERROR_MEM;
+        }
+    }
+    p->dicBufSize = dicBufSize;
+    p->prop = propNew;
+    return SZ_OK;
+}
+
+SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
+                const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode,
+                ELzmaStatus *status, ISzAllocPtr alloc)
+{
+    CLzmaDec p;
+    SRes res;
+    SizeT outSize = *destLen, inSize = *srcLen;
+    *destLen = *srcLen = 0;
+    *status = LZMA_STATUS_NOT_SPECIFIED;
+    if (inSize < RC_INIT_SIZE)
+        return SZ_ERROR_INPUT_EOF;
+    LzmaDec_Construct(&p);
+    RINOK(LzmaDec_AllocateProbs(&p, propData, propSize, alloc));
+    p.dic = dest;
+    p.dicBufSize = outSize;
+    LzmaDec_Init(&p);
+    *srcLen = inSize;
+    res = LzmaDec_DecodeToDic(&p, outSize, src, srcLen, finishMode, status);
+    *destLen = p.dicPos;
+    if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT)
+        res = SZ_ERROR_INPUT_EOF;
+    LzmaDec_FreeProbs(&p, alloc);
+    return res;
+}

+ 234 - 0
src/master/user/lzma/LzmaDec.h

@@ -0,0 +1,234 @@
+/* LzmaDec.h -- LZMA Decoder
+2018-04-21 : Igor Pavlov : Public domain */
+
+#ifndef __LZMA_DEC_H
+#define __LZMA_DEC_H
+
+#include "7zTypes.h"
+
+EXTERN_C_BEGIN
+
+/* #define _LZMA_PROB32 */
+/* _LZMA_PROB32 can increase the speed on some CPUs,
+   but memory usage for CLzmaDec::probs will be doubled in that case */
+
+typedef
+#ifdef _LZMA_PROB32
+  UInt32
+#else
+  UInt16
+#endif
+  CLzmaProb;
+
+
+/* ---------- LZMA Properties ---------- */
+
+#define LZMA_PROPS_SIZE 5
+
+typedef struct _CLzmaProps
+{
+  Byte lc;
+  Byte lp;
+  Byte pb;
+  Byte _pad_;
+  UInt32 dicSize;
+} CLzmaProps;
+
+/* LzmaProps_Decode - decodes properties
+Returns:
+  SZ_OK
+  SZ_ERROR_UNSUPPORTED - Unsupported properties
+*/
+
+SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size);
+
+
+/* ---------- LZMA Decoder state ---------- */
+
+/* LZMA_REQUIRED_INPUT_MAX = number of required input bytes for worst case.
+   Num bits = log2((2^11 / 31) ^ 22) + 26 < 134 + 26 = 160; */
+
+#define LZMA_REQUIRED_INPUT_MAX 20
+
+typedef struct
+{
+  /* Don't change this structure. ASM code can use it. */
+  CLzmaProps prop;
+  CLzmaProb *probs;
+  CLzmaProb *probs_1664;
+  Byte *dic;
+  SizeT dicBufSize;
+  SizeT dicPos;
+  const Byte *buf;
+  UInt32 range;
+  UInt32 code;
+  UInt32 processedPos;
+  UInt32 checkDicSize;
+  UInt32 reps[4];
+  UInt32 state;
+  UInt32 remainLen;
+
+  UInt32 numProbs;
+  unsigned tempBufSize;
+  Byte tempBuf[LZMA_REQUIRED_INPUT_MAX];
+} CLzmaDec;
+
+#define LzmaDec_Construct(p) { (p)->dic = NULL; (p)->probs = NULL; }
+
+void LzmaDec_Init(CLzmaDec *p);
+
+/* There are two types of LZMA streams:
+     - Stream with end mark. That end mark adds about 6 bytes to compressed size.
+     - Stream without end mark. You must know exact uncompressed size to decompress such stream. */
+
+typedef enum
+{
+  LZMA_FINISH_ANY,   /* finish at any point */
+  LZMA_FINISH_END    /* block must be finished at the end */
+} ELzmaFinishMode;
+
+/* ELzmaFinishMode has meaning only if the decoding reaches output limit !!!
+
+   You must use LZMA_FINISH_END, when you know that current output buffer
+   covers last bytes of block. In other cases you must use LZMA_FINISH_ANY.
+
+   If LZMA decoder sees end marker before reaching output limit, it returns SZ_OK,
+   and output value of destLen will be less than output buffer size limit.
+   You can check status result also.
+
+   You can use multiple checks to test data integrity after full decompression:
+     1) Check Result and "status" variable.
+     2) Check that output(destLen) = uncompressedSize, if you know real uncompressedSize.
+     3) Check that output(srcLen) = compressedSize, if you know real compressedSize.
+        You must use correct finish mode in that case. */
+
+typedef enum
+{
+  LZMA_STATUS_NOT_SPECIFIED,               /* use main error code instead */
+  LZMA_STATUS_FINISHED_WITH_MARK,          /* stream was finished with end mark. */
+  LZMA_STATUS_NOT_FINISHED,                /* stream was not finished */
+  LZMA_STATUS_NEEDS_MORE_INPUT,            /* you must provide more input bytes */
+  LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK  /* there is probability that stream was finished without end mark */
+} ELzmaStatus;
+
+/* ELzmaStatus is used only as output value for function call */
+
+
+/* ---------- Interfaces ---------- */
+
+/* There are 3 levels of interfaces:
+     1) Dictionary Interface
+     2) Buffer Interface
+     3) One Call Interface
+   You can select any of these interfaces, but don't mix functions from different
+   groups for same object. */
+
+
+/* There are two variants to allocate state for Dictionary Interface:
+     1) LzmaDec_Allocate / LzmaDec_Free
+     2) LzmaDec_AllocateProbs / LzmaDec_FreeProbs
+   You can use variant 2, if you set dictionary buffer manually.
+   For Buffer Interface you must always use variant 1.
+
+LzmaDec_Allocate* can return:
+  SZ_OK
+  SZ_ERROR_MEM         - Memory allocation error
+  SZ_ERROR_UNSUPPORTED - Unsupported properties
+*/
+   
+SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAllocPtr alloc);
+void LzmaDec_FreeProbs(CLzmaDec *p, ISzAllocPtr alloc);
+
+SRes LzmaDec_Allocate(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAllocPtr alloc);
+void LzmaDec_Free(CLzmaDec *p, ISzAllocPtr alloc);
+
+/* ---------- Dictionary Interface ---------- */
+
+/* You can use it, if you want to eliminate the overhead for data copying from
+   dictionary to some other external buffer.
+   You must work with CLzmaDec variables directly in this interface.
+
+   STEPS:
+     LzmaDec_Construct()
+     LzmaDec_Allocate()
+     for (each new stream)
+     {
+       LzmaDec_Init()
+       while (it needs more decompression)
+       {
+         LzmaDec_DecodeToDic()
+         use data from CLzmaDec::dic and update CLzmaDec::dicPos
+       }
+     }
+     LzmaDec_Free()
+*/
+
+/* LzmaDec_DecodeToDic
+   
+   The decoding to internal dictionary buffer (CLzmaDec::dic).
+   You must manually update CLzmaDec::dicPos, if it reaches CLzmaDec::dicBufSize !!!
+
+finishMode:
+  It has meaning only if the decoding reaches output limit (dicLimit).
+  LZMA_FINISH_ANY - Decode just dicLimit bytes.
+  LZMA_FINISH_END - Stream must be finished after dicLimit.
+
+Returns:
+  SZ_OK
+    status:
+      LZMA_STATUS_FINISHED_WITH_MARK
+      LZMA_STATUS_NOT_FINISHED
+      LZMA_STATUS_NEEDS_MORE_INPUT
+      LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK
+  SZ_ERROR_DATA - Data error
+*/
+
+SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit,
+    const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);
+
+
+/* ---------- Buffer Interface ---------- */
+
+/* It's zlib-like interface.
+   See LzmaDec_DecodeToDic description for information about STEPS and return results,
+   but you must use LzmaDec_DecodeToBuf instead of LzmaDec_DecodeToDic and you don't need
+   to work with CLzmaDec variables manually.
+
+finishMode:
+  It has meaning only if the decoding reaches output limit (*destLen).
+  LZMA_FINISH_ANY - Decode just destLen bytes.
+  LZMA_FINISH_END - Stream must be finished after (*destLen).
+*/
+
+SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen,
+    const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);
+
+
+/* ---------- One Call Interface ---------- */
+
+/* LzmaDecode
+
+finishMode:
+  It has meaning only if the decoding reaches output limit (*destLen).
+  LZMA_FINISH_ANY - Decode just destLen bytes.
+  LZMA_FINISH_END - Stream must be finished after (*destLen).
+
+Returns:
+  SZ_OK
+    status:
+      LZMA_STATUS_FINISHED_WITH_MARK
+      LZMA_STATUS_NOT_FINISHED
+      LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK
+  SZ_ERROR_DATA - Data error
+  SZ_ERROR_MEM  - Memory allocation error
+  SZ_ERROR_UNSUPPORTED - Unsupported properties
+  SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src).
+*/
+
+SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
+    const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode,
+    ELzmaStatus *status, ISzAllocPtr alloc);
+
+EXTERN_C_END
+
+#endif

+ 2991 - 0
src/master/user/lzma/LzmaEnc.c

@@ -0,0 +1,2991 @@
+/* LzmaEnc.c -- LZMA Encoder
+2019-01-10: Igor Pavlov : Public domain */
+
+#include "Precomp.h"
+
+#include <string.h>
+
+/* #define SHOW_STAT */
+/* #define SHOW_STAT2 */
+
+#if defined(SHOW_STAT) || defined(SHOW_STAT2)
+#include <stdio.h>
+#endif
+
+#include "LzmaEnc.h"
+
+#include "LzFind.h"
+#ifndef _7ZIP_ST
+#include "LzFindMt.h"
+#endif
+
+#ifdef SHOW_STAT
+static unsigned g_STAT_OFFSET = 0;
+#endif
+
+#define kLzmaMaxHistorySize ((UInt32)3 << 29)
+/* #define kLzmaMaxHistorySize ((UInt32)7 << 29) */
+
+#define kNumTopBits 24
+#define kTopValue ((UInt32)1 << kNumTopBits)
+
+#define kNumBitModelTotalBits 11
+#define kBitModelTotal (1 << kNumBitModelTotalBits)
+#define kNumMoveBits 5
+#define kProbInitValue (kBitModelTotal >> 1)
+
+#define kNumMoveReducingBits 4
+#define kNumBitPriceShiftBits 4
+#define kBitPrice (1 << kNumBitPriceShiftBits)
+
+#define REP_LEN_COUNT 64
+
+void LzmaEncProps_Init(CLzmaEncProps *p)
+{
+    p->level = 5;
+    p->dictSize = p->mc = 0;
+    p->reduceSize = (UInt64) (Int64) - 1;
+    p->lc = p->lp = p->pb = p->algo = p->fb = p->btMode = p->numHashBytes = p->numThreads = -1;
+    p->writeEndMark = 0;
+}
+
+void LzmaEncProps_Normalize(CLzmaEncProps *p)
+{
+    int level = p->level;
+    if (level < 0) level = 5;
+    p->level = level;
+
+    if (p->dictSize == 0) p->dictSize = (level <= 5 ? (1 << (level * 2 + 14)) : (level <= 7 ? (1 << 25) : (1 << 26)));
+    if (p->dictSize > p->reduceSize)
+    {
+        unsigned i;
+        UInt32 reduceSize = (UInt32) p->reduceSize;
+        for (i = 11; i <= 30; i++)
+        {
+            if (reduceSize <= ((UInt32) 2 << i))
+            {
+                p->dictSize = ((UInt32) 2 << i);
+                break;
+            }
+            if (reduceSize <= ((UInt32) 3 << i))
+            {
+                p->dictSize = ((UInt32) 3 << i);
+                break;
+            }
+        }
+    }
+
+    if (p->lc < 0) p->lc = 3;
+    if (p->lp < 0) p->lp = 0;
+    if (p->pb < 0) p->pb = 2;
+
+    if (p->algo < 0) p->algo = (level < 5 ? 0 : 1);
+    if (p->fb < 0) p->fb = (level < 7 ? 32 : 64);
+    if (p->btMode < 0) p->btMode = (p->algo == 0 ? 0 : 1);
+    if (p->numHashBytes < 0) p->numHashBytes = 4;
+    if (p->mc == 0) p->mc = (16 + (p->fb >> 1)) >> (p->btMode ? 0 : 1);
+
+    if (p->numThreads < 0)
+        p->numThreads =
+#ifndef _7ZIP_ST
+            ((p->btMode && p->algo) ? 2 : 1);
+#else
+            1;
+#endif
+}
+
+UInt32 LzmaEncProps_GetDictSize(const CLzmaEncProps *props2)
+{
+    CLzmaEncProps props = *props2;
+    LzmaEncProps_Normalize(&props);
+    return props.dictSize;
+}
+
+#if (_MSC_VER >= 1400)
+/* BSR code is fast for some new CPUs */
+/* #define LZMA_LOG_BSR */
+#endif
+
+#ifdef LZMA_LOG_BSR
+
+#define kDicLogSizeMaxCompress 32
+
+#define BSR2_RET(pos, res) { unsigned long zz; _BitScanReverse(&zz, (pos)); res = (zz + zz) + ((pos >> (zz - 1)) & 1); }
+
+static unsigned GetPosSlot1(UInt32 pos)
+{
+    unsigned res;
+    BSR2_RET(pos, res);
+    return res;
+}
+#define GetPosSlot2(pos, res) { BSR2_RET(pos, res); }
+#define GetPosSlot(pos, res) { if (pos < 2) res = pos; else BSR2_RET(pos, res); }
+
+#else
+
+#define kNumLogBits (9 + sizeof(size_t) / 2)
+/* #define kNumLogBits (11 + sizeof(size_t) / 8 * 3) */
+
+#define kDicLogSizeMaxCompress ((kNumLogBits - 1) * 2 + 7)
+
+static void LzmaEnc_FastPosInit(Byte *g_FastPos)
+{
+    unsigned slot;
+    g_FastPos[0] = 0;
+    g_FastPos[1] = 1;
+    g_FastPos += 2;
+
+    for (slot = 2; slot < kNumLogBits * 2; slot++)
+    {
+        size_t k = ((size_t) 1 << ((slot >> 1) - 1));
+        size_t j;
+        for (j = 0; j < k; j++)
+            g_FastPos[j] = (Byte) slot;
+        g_FastPos += k;
+    }
+}
+
+/* we can use ((limit - pos) >> 31) only if (pos < ((UInt32)1 << 31)) */
+/*
+#define BSR2_RET(pos, res) { unsigned zz = 6 + ((kNumLogBits - 1) & \
+  (0 - (((((UInt32)1 << (kNumLogBits + 6)) - 1) - pos) >> 31))); \
+  res = p->g_FastPos[pos >> zz] + (zz * 2); }
+ */
+
+/*
+#define BSR2_RET(pos, res) { unsigned zz = 6 + ((kNumLogBits - 1) & \
+  (0 - (((((UInt32)1 << (kNumLogBits)) - 1) - (pos >> 6)) >> 31))); \
+  res = p->g_FastPos[pos >> zz] + (zz * 2); }
+ */
+
+#define BSR2_RET(pos, res) { unsigned zz = (pos < (1 << (kNumLogBits + 6))) ? 6 : 6 + kNumLogBits - 1; \
+  res = p->g_FastPos[pos >> zz] + (zz * 2); }
+
+/*
+#define BSR2_RET(pos, res) { res = (pos < (1 << (kNumLogBits + 6))) ? \
+  p->g_FastPos[pos >> 6] + 12 : \
+  p->g_FastPos[pos >> (6 + kNumLogBits - 1)] + (6 + (kNumLogBits - 1)) * 2; }
+ */
+
+#define GetPosSlot1(pos) p->g_FastPos[pos]
+#define GetPosSlot2(pos, res) { BSR2_RET(pos, res); }
+#define GetPosSlot(pos, res) { if (pos < kNumFullDistances) res = p->g_FastPos[pos & (kNumFullDistances - 1)]; else BSR2_RET(pos, res); }
+
+#endif
+
+
+#define LZMA_NUM_REPS 4
+
+typedef UInt16 CState;
+typedef UInt16 CExtra;
+
+typedef struct
+{
+    UInt32 price;
+    CState state;
+    CExtra extra;
+    // 0   : normal
+    // 1   : LIT : MATCH
+    // > 1 : MATCH (extra-1) : LIT : REP0 (len)
+    UInt32 len;
+    UInt32 dist;
+    UInt32 reps[LZMA_NUM_REPS];
+} COptimal;
+
+
+// 18.06
+#define kNumOpts (1 << 11)
+#define kPackReserve (kNumOpts * 8)
+// #define kNumOpts (1 << 12)
+// #define kPackReserve (1 + kNumOpts * 2)
+
+#define kNumLenToPosStates 4
+#define kNumPosSlotBits 6
+#define kDicLogSizeMin 0
+#define kDicLogSizeMax 32
+#define kDistTableSizeMax (kDicLogSizeMax * 2)
+
+#define kNumAlignBits 4
+#define kAlignTableSize (1 << kNumAlignBits)
+#define kAlignMask (kAlignTableSize - 1)
+
+#define kStartPosModelIndex 4
+#define kEndPosModelIndex 14
+#define kNumFullDistances (1 << (kEndPosModelIndex >> 1))
+
+typedef
+#ifdef _LZMA_PROB32
+UInt32
+#else
+UInt16
+#endif
+CLzmaProb;
+
+#define LZMA_PB_MAX 4
+#define LZMA_LC_MAX 8
+#define LZMA_LP_MAX 4
+
+#define LZMA_NUM_PB_STATES_MAX (1 << LZMA_PB_MAX)
+
+#define kLenNumLowBits 3
+#define kLenNumLowSymbols (1 << kLenNumLowBits)
+#define kLenNumHighBits 8
+#define kLenNumHighSymbols (1 << kLenNumHighBits)
+#define kLenNumSymbolsTotal (kLenNumLowSymbols * 2 + kLenNumHighSymbols)
+
+#define LZMA_MATCH_LEN_MIN 2
+#define LZMA_MATCH_LEN_MAX (LZMA_MATCH_LEN_MIN + kLenNumSymbolsTotal - 1)
+
+#define kNumStates 12
+
+typedef struct
+{
+    CLzmaProb low[LZMA_NUM_PB_STATES_MAX << (kLenNumLowBits + 1)];
+    CLzmaProb high[kLenNumHighSymbols];
+} CLenEnc;
+
+typedef struct
+{
+    unsigned tableSize;
+    UInt32 prices[LZMA_NUM_PB_STATES_MAX][kLenNumSymbolsTotal];
+    // UInt32 prices1[LZMA_NUM_PB_STATES_MAX][kLenNumLowSymbols * 2];
+    // UInt32 prices2[kLenNumSymbolsTotal];
+} CLenPriceEnc;
+
+#define GET_PRICE_LEN(p, posState, len) \
+    ((p)->prices[posState][(size_t)(len) - LZMA_MATCH_LEN_MIN])
+
+/*
+#define GET_PRICE_LEN(p, posState, len) \
+    ((p)->prices2[(size_t)(len) - 2] + ((p)->prices1[posState][((len) - 2) & (kLenNumLowSymbols * 2 - 1)] & (((len) - 2 - kLenNumLowSymbols * 2) >> 9)))
+ */
+
+typedef struct
+{
+    UInt32 range;
+    unsigned cache;
+    UInt64 low;
+    UInt64 cacheSize;
+    Byte *buf;
+    Byte *bufLim;
+    Byte *bufBase;
+    ISeqOutStream *outStream;
+    UInt64 processed;
+    SRes res;
+} CRangeEnc;
+
+typedef struct
+{
+    CLzmaProb *litProbs;
+
+    unsigned state;
+    UInt32 reps[LZMA_NUM_REPS];
+
+    CLzmaProb posAlignEncoder[1 << kNumAlignBits];
+    CLzmaProb isRep[kNumStates];
+    CLzmaProb isRepG0[kNumStates];
+    CLzmaProb isRepG1[kNumStates];
+    CLzmaProb isRepG2[kNumStates];
+    CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX];
+    CLzmaProb isRep0Long[kNumStates][LZMA_NUM_PB_STATES_MAX];
+
+    CLzmaProb posSlotEncoder[kNumLenToPosStates][1 << kNumPosSlotBits];
+    CLzmaProb posEncoders[kNumFullDistances];
+
+    CLenEnc lenProbs;
+    CLenEnc repLenProbs;
+
+} CSaveState;
+
+
+typedef UInt32 CProbPrice;
+
+typedef struct
+{
+    void *matchFinderObj;
+    IMatchFinder matchFinder;
+
+    unsigned optCur;
+    unsigned optEnd;
+
+    unsigned longestMatchLen;
+    unsigned numPairs;
+    UInt32 numAvail;
+
+    unsigned state;
+    unsigned numFastBytes;
+    unsigned additionalOffset;
+    UInt32 reps[LZMA_NUM_REPS];
+    unsigned lpMask, pbMask;
+    CLzmaProb *litProbs;
+    CRangeEnc rc;
+
+    UInt32 backRes;
+
+    unsigned lc, lp, pb;
+    unsigned lclp;
+
+    BoolInt fastMode;
+    BoolInt writeEndMark;
+    BoolInt finished;
+    BoolInt multiThread;
+    BoolInt needInit;
+    // BoolInt _maxMode;
+
+    UInt64 nowPos64;
+
+    unsigned matchPriceCount;
+    // unsigned alignPriceCount;
+    int repLenEncCounter;
+
+    unsigned distTableSize;
+
+    UInt32 dictSize;
+    SRes result;
+
+#ifndef _7ZIP_ST
+    BoolInt mtMode;
+    // begin of CMatchFinderMt is used in LZ thread
+    CMatchFinderMt matchFinderMt;
+    // end of CMatchFinderMt is used in BT and HASH threads
+#endif
+
+    CMatchFinder matchFinderBase;
+
+#ifndef _7ZIP_ST
+    Byte pad[128];
+#endif
+
+    // LZ thread
+    CProbPrice ProbPrices[kBitModelTotal >> kNumMoveReducingBits];
+
+    UInt32 matches[LZMA_MATCH_LEN_MAX * 2 + 2 + 1];
+
+    UInt32 alignPrices[kAlignTableSize];
+    UInt32 posSlotPrices[kNumLenToPosStates][kDistTableSizeMax];
+    UInt32 distancesPrices[kNumLenToPosStates][kNumFullDistances];
+
+    CLzmaProb posAlignEncoder[1 << kNumAlignBits];
+    CLzmaProb isRep[kNumStates];
+    CLzmaProb isRepG0[kNumStates];
+    CLzmaProb isRepG1[kNumStates];
+    CLzmaProb isRepG2[kNumStates];
+    CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX];
+    CLzmaProb isRep0Long[kNumStates][LZMA_NUM_PB_STATES_MAX];
+    CLzmaProb posSlotEncoder[kNumLenToPosStates][1 << kNumPosSlotBits];
+    CLzmaProb posEncoders[kNumFullDistances];
+
+    CLenEnc lenProbs;
+    CLenEnc repLenProbs;
+
+#ifndef LZMA_LOG_BSR
+    Byte g_FastPos[1 << kNumLogBits];
+#endif
+
+    CLenPriceEnc lenEnc;
+    CLenPriceEnc repLenEnc;
+
+    COptimal opt[kNumOpts];
+
+    CSaveState saveState;
+
+#ifndef _7ZIP_ST
+    Byte pad2[128];
+#endif
+} CLzmaEnc;
+
+
+
+#define COPY_ARR(dest, src, arr) memcpy(dest->arr, src->arr, sizeof(src->arr));
+
+void LzmaEnc_SaveState(CLzmaEncHandle pp)
+{
+    CLzmaEnc *p = (CLzmaEnc *) pp;
+    CSaveState *dest = &p->saveState;
+
+    dest->state = p->state;
+
+    dest->lenProbs = p->lenProbs;
+    dest->repLenProbs = p->repLenProbs;
+
+    COPY_ARR(dest, p, reps);
+
+    COPY_ARR(dest, p, posAlignEncoder);
+    COPY_ARR(dest, p, isRep);
+    COPY_ARR(dest, p, isRepG0);
+    COPY_ARR(dest, p, isRepG1);
+    COPY_ARR(dest, p, isRepG2);
+    COPY_ARR(dest, p, isMatch);
+    COPY_ARR(dest, p, isRep0Long);
+    COPY_ARR(dest, p, posSlotEncoder);
+    COPY_ARR(dest, p, posEncoders);
+
+    memcpy(dest->litProbs, p->litProbs, ((UInt32) 0x300 << p->lclp) * sizeof (CLzmaProb));
+}
+
+void LzmaEnc_RestoreState(CLzmaEncHandle pp)
+{
+    CLzmaEnc *dest = (CLzmaEnc *) pp;
+    const CSaveState *p = &dest->saveState;
+
+    dest->state = p->state;
+
+    dest->lenProbs = p->lenProbs;
+    dest->repLenProbs = p->repLenProbs;
+
+    COPY_ARR(dest, p, reps);
+
+    COPY_ARR(dest, p, posAlignEncoder);
+    COPY_ARR(dest, p, isRep);
+    COPY_ARR(dest, p, isRepG0);
+    COPY_ARR(dest, p, isRepG1);
+    COPY_ARR(dest, p, isRepG2);
+    COPY_ARR(dest, p, isMatch);
+    COPY_ARR(dest, p, isRep0Long);
+    COPY_ARR(dest, p, posSlotEncoder);
+    COPY_ARR(dest, p, posEncoders);
+
+    memcpy(dest->litProbs, p->litProbs, ((UInt32) 0x300 << dest->lclp) * sizeof (CLzmaProb));
+}
+
+SRes LzmaEnc_SetProps(CLzmaEncHandle pp, const CLzmaEncProps *props2)
+{
+    CLzmaEnc *p = (CLzmaEnc *) pp;
+    CLzmaEncProps props = *props2;
+    LzmaEncProps_Normalize(&props);
+
+    if (props.lc > LZMA_LC_MAX
+            || props.lp > LZMA_LP_MAX
+            || props.pb > LZMA_PB_MAX
+            || props.dictSize > ((UInt64) 1 << kDicLogSizeMaxCompress)
+            || props.dictSize > kLzmaMaxHistorySize)
+        return SZ_ERROR_PARAM;
+
+    p->dictSize = props.dictSize;
+    {
+        unsigned fb = props.fb;
+        if (fb < 5)
+            fb = 5;
+        if (fb > LZMA_MATCH_LEN_MAX)
+            fb = LZMA_MATCH_LEN_MAX;
+        p->numFastBytes = fb;
+    }
+    p->lc = props.lc;
+    p->lp = props.lp;
+    p->pb = props.pb;
+    p->fastMode = (props.algo == 0);
+    // p->_maxMode = True;
+    p->matchFinderBase.btMode = (Byte) (props.btMode ? 1 : 0);
+    {
+        unsigned numHashBytes = 4;
+        if (props.btMode)
+        {
+            if (props.numHashBytes < 2)
+                numHashBytes = 2;
+            else if (props.numHashBytes < 4)
+                numHashBytes = props.numHashBytes;
+        }
+        p->matchFinderBase.numHashBytes = numHashBytes;
+    }
+
+    p->matchFinderBase.cutValue = props.mc;
+
+    p->writeEndMark = props.writeEndMark;
+
+#ifndef _7ZIP_ST
+    /*
+    if (newMultiThread != _multiThread)
+    {
+      ReleaseMatchFinder();
+      _multiThread = newMultiThread;
+    }
+     */
+    p->multiThread = (props.numThreads > 1);
+#endif
+
+    return SZ_OK;
+}
+
+void LzmaEnc_SetDataSize(CLzmaEncHandle pp, UInt64 expectedDataSiize)
+{
+    CLzmaEnc *p = (CLzmaEnc *) pp;
+    p->matchFinderBase.expectedDataSize = expectedDataSiize;
+}
+
+
+#define kState_Start 0
+#define kState_LitAfterMatch 4
+#define kState_LitAfterRep   5
+#define kState_MatchAfterLit 7
+#define kState_RepAfterLit   8
+
+static const Byte kLiteralNextStates[kNumStates] = {0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5};
+static const Byte kMatchNextStates[kNumStates] = {7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10};
+static const Byte kRepNextStates[kNumStates] = {8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11};
+static const Byte kShortRepNextStates[kNumStates] = {9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11};
+
+#define IsLitState(s) ((s) < 7)
+#define GetLenToPosState2(len) (((len) < kNumLenToPosStates - 1) ? (len) : kNumLenToPosStates - 1)
+#define GetLenToPosState(len) (((len) < kNumLenToPosStates + 1) ? (len) - 2 : kNumLenToPosStates - 1)
+
+#define kInfinityPrice (1 << 30)
+
+static void RangeEnc_Construct(CRangeEnc *p)
+{
+    p->outStream = NULL;
+    p->bufBase = NULL;
+}
+
+#define RangeEnc_GetProcessed(p)       ((p)->processed + ((p)->buf - (p)->bufBase) + (p)->cacheSize)
+#define RangeEnc_GetProcessed_sizet(p) ((size_t)(p)->processed + ((p)->buf - (p)->bufBase) + (size_t)(p)->cacheSize)
+
+#define RC_BUF_SIZE (1 << 16)
+
+static int RangeEnc_Alloc(CRangeEnc *p, ISzAllocPtr alloc)
+{
+    if (!p->bufBase)
+    {
+        p->bufBase = (Byte *) ISzAlloc_Alloc(alloc, RC_BUF_SIZE);
+        if (!p->bufBase)
+            return 0;
+        p->bufLim = p->bufBase + RC_BUF_SIZE;
+    }
+    return 1;
+}
+
+static void RangeEnc_Free(CRangeEnc *p, ISzAllocPtr alloc)
+{
+    ISzAlloc_Free(alloc, p->bufBase);
+    p->bufBase = 0;
+}
+
+static void RangeEnc_Init(CRangeEnc *p)
+{
+    /* Stream.Init(); */
+    p->range = 0xFFFFFFFF;
+    p->cache = 0;
+    p->low = 0;
+    p->cacheSize = 0;
+
+    p->buf = p->bufBase;
+
+    p->processed = 0;
+    p->res = SZ_OK;
+}
+
+MY_NO_INLINE static void RangeEnc_FlushStream(CRangeEnc *p)
+{
+    size_t num;
+    if (p->res != SZ_OK)
+        return;
+    num = p->buf - p->bufBase;
+    if (num != ISeqOutStream_Write(p->outStream, p->bufBase, num))
+        p->res = SZ_ERROR_WRITE;
+    p->processed += num;
+    p->buf = p->bufBase;
+}
+
+MY_NO_INLINE static void MY_FAST_CALL RangeEnc_ShiftLow(CRangeEnc *p)
+{
+    UInt32 low = (UInt32) p->low;
+    unsigned high = (unsigned) (p->low >> 32);
+    p->low = (UInt32) (low << 8);
+    if (low < (UInt32) 0xFF000000 || high != 0)
+    {
+        {
+            Byte *buf = p->buf;
+            *buf++ = (Byte) (p->cache + high);
+            p->cache = (unsigned) (low >> 24);
+            p->buf = buf;
+            if (buf == p->bufLim)
+                RangeEnc_FlushStream(p);
+            if (p->cacheSize == 0)
+                return;
+        }
+        high += 0xFF;
+        for (;;)
+        {
+            Byte *buf = p->buf;
+            *buf++ = (Byte) (high);
+            p->buf = buf;
+            if (buf == p->bufLim)
+                RangeEnc_FlushStream(p);
+            if (--p->cacheSize == 0)
+                return;
+        }
+    }
+    p->cacheSize++;
+}
+
+static void RangeEnc_FlushData(CRangeEnc *p)
+{
+    int i;
+    for (i = 0; i < 5; i++)
+        RangeEnc_ShiftLow(p);
+}
+
+#define RC_NORM(p) if (range < kTopValue) { range <<= 8; RangeEnc_ShiftLow(p); }
+
+#define RC_BIT_PRE(p, prob) \
+  ttt = *(prob); \
+  newBound = (range >> kNumBitModelTotalBits) * ttt;
+
+// #define _LZMA_ENC_USE_BRANCH
+
+#ifdef _LZMA_ENC_USE_BRANCH
+
+#define RC_BIT(p, prob, bit) { \
+  RC_BIT_PRE(p, prob) \
+  if (bit == 0) { range = newBound; ttt += (kBitModelTotal - ttt) >> kNumMoveBits; } \
+  else { (p)->low += newBound; range -= newBound; ttt -= ttt >> kNumMoveBits; } \
+  *(prob) = (CLzmaProb)ttt; \
+  RC_NORM(p) \
+  }
+
+#else
+
+#define RC_BIT(p, prob, bit) { \
+  UInt32 mask; \
+  RC_BIT_PRE(p, prob) \
+  mask = 0 - (UInt32)bit; \
+  range &= mask; \
+  mask &= newBound; \
+  range -= mask; \
+  (p)->low += mask; \
+  mask = (UInt32)bit - 1; \
+  range += newBound & mask; \
+  mask &= (kBitModelTotal - ((1 << kNumMoveBits) - 1)); \
+  mask += ((1 << kNumMoveBits) - 1); \
+  ttt += (Int32)(mask - ttt) >> kNumMoveBits; \
+  *(prob) = (CLzmaProb)ttt; \
+  RC_NORM(p) \
+  }
+
+#endif
+
+
+
+
+#define RC_BIT_0_BASE(p, prob) \
+  range = newBound; *(prob) = (CLzmaProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits));
+
+#define RC_BIT_1_BASE(p, prob) \
+  range -= newBound; (p)->low += newBound; *(prob) = (CLzmaProb)(ttt - (ttt >> kNumMoveBits)); \
+
+#define RC_BIT_0(p, prob) \
+  RC_BIT_0_BASE(p, prob) \
+  RC_NORM(p)
+
+#define RC_BIT_1(p, prob) \
+  RC_BIT_1_BASE(p, prob) \
+  RC_NORM(p)
+
+static void RangeEnc_EncodeBit_0(CRangeEnc *p, CLzmaProb *prob)
+{
+    UInt32 range, ttt, newBound;
+    range = p->range;
+    RC_BIT_PRE(p, prob)
+    RC_BIT_0(p, prob)
+    p->range = range;
+}
+
+static void LitEnc_Encode(CRangeEnc *p, CLzmaProb *probs, UInt32 sym)
+{
+    UInt32 range = p->range;
+    sym |= 0x100;
+    do
+    {
+        UInt32 ttt, newBound;
+        // RangeEnc_EncodeBit(p, probs + (sym >> 8), (sym >> 7) & 1);
+        CLzmaProb *prob = probs + (sym >> 8);
+        UInt32 bit = (sym >> 7) & 1;
+        sym <<= 1;
+        RC_BIT(p, prob, bit);
+    }
+    while (sym < 0x10000);
+    p->range = range;
+}
+
+static void LitEnc_EncodeMatched(CRangeEnc *p, CLzmaProb *probs, UInt32 sym, UInt32 matchByte)
+{
+    UInt32 range = p->range;
+    UInt32 offs = 0x100;
+    sym |= 0x100;
+    do
+    {
+        UInt32 ttt, newBound;
+        CLzmaProb *prob;
+        UInt32 bit;
+        matchByte <<= 1;
+        // RangeEnc_EncodeBit(p, probs + (offs + (matchByte & offs) + (sym >> 8)), (sym >> 7) & 1);
+        prob = probs + (offs + (matchByte & offs) + (sym >> 8));
+        bit = (sym >> 7) & 1;
+        sym <<= 1;
+        offs &= ~(matchByte ^ sym);
+        RC_BIT(p, prob, bit);
+    }
+    while (sym < 0x10000);
+    p->range = range;
+}
+
+static void LzmaEnc_InitPriceTables(CProbPrice *ProbPrices)
+{
+    UInt32 i;
+    for (i = 0; i < (kBitModelTotal >> kNumMoveReducingBits); i++)
+    {
+        const unsigned kCyclesBits = kNumBitPriceShiftBits;
+        UInt32 w = (i << kNumMoveReducingBits) + (1 << (kNumMoveReducingBits - 1));
+        unsigned bitCount = 0;
+        unsigned j;
+        for (j = 0; j < kCyclesBits; j++)
+        {
+            w = w * w;
+            bitCount <<= 1;
+            while (w >= ((UInt32) 1 << 16))
+            {
+                w >>= 1;
+                bitCount++;
+            }
+        }
+        ProbPrices[i] = (CProbPrice) ((kNumBitModelTotalBits << kCyclesBits) - 15 - bitCount);
+        // printf("\n%3d: %5d", i, ProbPrices[i]);
+    }
+}
+
+
+#define GET_PRICE(prob, bit) \
+  p->ProbPrices[((prob) ^ (unsigned)(((-(int)(bit))) & (kBitModelTotal - 1))) >> kNumMoveReducingBits];
+
+#define GET_PRICEa(prob, bit) \
+     ProbPrices[((prob) ^ (unsigned)((-((int)(bit))) & (kBitModelTotal - 1))) >> kNumMoveReducingBits];
+
+#define GET_PRICE_0(prob) p->ProbPrices[(prob) >> kNumMoveReducingBits]
+#define GET_PRICE_1(prob) p->ProbPrices[((prob) ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits]
+
+#define GET_PRICEa_0(prob) ProbPrices[(prob) >> kNumMoveReducingBits]
+#define GET_PRICEa_1(prob) ProbPrices[((prob) ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits]
+
+static UInt32 LitEnc_GetPrice(const CLzmaProb *probs, UInt32 sym, const CProbPrice *ProbPrices)
+{
+    UInt32 price = 0;
+    sym |= 0x100;
+    do
+    {
+        unsigned bit = sym & 1;
+        sym >>= 1;
+        price += GET_PRICEa(probs[sym], bit);
+    }
+    while (sym >= 2);
+    return price;
+}
+
+static UInt32 LitEnc_Matched_GetPrice(const CLzmaProb *probs, UInt32 sym, UInt32 matchByte, const CProbPrice *ProbPrices)
+{
+    UInt32 price = 0;
+    UInt32 offs = 0x100;
+    sym |= 0x100;
+    do
+    {
+        matchByte <<= 1;
+        price += GET_PRICEa(probs[offs + (matchByte & offs) + (sym >> 8)], (sym >> 7) & 1);
+        sym <<= 1;
+        offs &= ~(matchByte ^ sym);
+    }
+    while (sym < 0x10000);
+    return price;
+}
+
+static void RcTree_ReverseEncode(CRangeEnc *rc, CLzmaProb *probs, unsigned numBits, unsigned sym)
+{
+    UInt32 range = rc->range;
+    unsigned m = 1;
+    do
+    {
+        UInt32 ttt, newBound;
+        unsigned bit = sym & 1;
+        // RangeEnc_EncodeBit(rc, probs + m, bit);
+        sym >>= 1;
+        RC_BIT(rc, probs + m, bit);
+        m = (m << 1) | bit;
+    }
+    while (--numBits);
+    rc->range = range;
+}
+
+static void LenEnc_Init(CLenEnc *p)
+{
+    unsigned i;
+    for (i = 0; i < (LZMA_NUM_PB_STATES_MAX << (kLenNumLowBits + 1)); i++)
+        p->low[i] = kProbInitValue;
+    for (i = 0; i < kLenNumHighSymbols; i++)
+        p->high[i] = kProbInitValue;
+}
+
+static void LenEnc_Encode(CLenEnc *p, CRangeEnc *rc, unsigned sym, unsigned posState)
+{
+    UInt32 range, ttt, newBound;
+    CLzmaProb *probs = p->low;
+    range = rc->range;
+    RC_BIT_PRE(rc, probs);
+    if (sym >= kLenNumLowSymbols)
+    {
+        RC_BIT_1(rc, probs);
+        probs += kLenNumLowSymbols;
+        RC_BIT_PRE(rc, probs);
+        if (sym >= kLenNumLowSymbols * 2)
+        {
+            RC_BIT_1(rc, probs);
+            rc->range = range;
+            // RcTree_Encode(rc, p->high, kLenNumHighBits, sym - kLenNumLowSymbols * 2);
+            LitEnc_Encode(rc, p->high, sym - kLenNumLowSymbols * 2);
+            return;
+        }
+        sym -= kLenNumLowSymbols;
+    }
+
+    // RcTree_Encode(rc, probs + (posState << kLenNumLowBits), kLenNumLowBits, sym);
+    {
+        unsigned m;
+        unsigned bit;
+        RC_BIT_0(rc, probs);
+        probs += (posState << (1 + kLenNumLowBits));
+        bit = (sym >> 2);
+        RC_BIT(rc, probs + 1, bit);
+        m = (1 << 1) + bit;
+        bit = (sym >> 1) & 1;
+        RC_BIT(rc, probs + m, bit);
+        m = (m << 1) + bit;
+        bit = sym & 1;
+        RC_BIT(rc, probs + m, bit);
+        rc->range = range;
+    }
+}
+
+static void SetPrices_3(const CLzmaProb *probs, UInt32 startPrice, UInt32 *prices, const CProbPrice *ProbPrices)
+{
+    unsigned i;
+    for (i = 0; i < 8; i += 2)
+    {
+        UInt32 price = startPrice;
+        UInt32 prob;
+        price += GET_PRICEa(probs[1 ], (i >> 2));
+        price += GET_PRICEa(probs[2 + (i >> 2)], (i >> 1) & 1);
+        prob = probs[4 + (i >> 1)];
+        prices[i ] = price + GET_PRICEa_0(prob);
+        prices[i + 1] = price + GET_PRICEa_1(prob);
+    }
+}
+
+MY_NO_INLINE static void MY_FAST_CALL LenPriceEnc_UpdateTables(
+                                                               CLenPriceEnc *p,
+                                                               unsigned numPosStates,
+                                                               const CLenEnc *enc,
+                                                               const CProbPrice *ProbPrices)
+{
+    UInt32 b;
+
+    {
+        unsigned prob = enc->low[0];
+        UInt32 a, c;
+        unsigned posState;
+        b = GET_PRICEa_1(prob);
+        a = GET_PRICEa_0(prob);
+        c = b + GET_PRICEa_0(enc->low[kLenNumLowSymbols]);
+        for (posState = 0; posState < numPosStates; posState++)
+        {
+            UInt32 *prices = p->prices[posState];
+            const CLzmaProb *probs = enc->low + (posState << (1 + kLenNumLowBits));
+            SetPrices_3(probs, a, prices, ProbPrices);
+            SetPrices_3(probs + kLenNumLowSymbols, c, prices + kLenNumLowSymbols, ProbPrices);
+        }
+    }
+
+    /*
+    {
+      unsigned i;
+      UInt32 b;
+      a = GET_PRICEa_0(enc->low[0]);
+      for (i = 0; i < kLenNumLowSymbols; i++)
+        p->prices2[i] = a;
+      a = GET_PRICEa_1(enc->low[0]);
+      b = a + GET_PRICEa_0(enc->low[kLenNumLowSymbols]);
+      for (i = kLenNumLowSymbols; i < kLenNumLowSymbols * 2; i++)
+        p->prices2[i] = b;
+      a += GET_PRICEa_1(enc->low[kLenNumLowSymbols]);
+    }
+     */
+
+    // p->counter = numSymbols;
+    // p->counter = 64;
+
+    {
+        unsigned i = p->tableSize;
+
+        if (i > kLenNumLowSymbols * 2)
+        {
+            const CLzmaProb *probs = enc->high;
+            UInt32 *prices = p->prices[0] + kLenNumLowSymbols * 2;
+            i -= kLenNumLowSymbols * 2 - 1;
+            i >>= 1;
+            b += GET_PRICEa_1(enc->low[kLenNumLowSymbols]);
+            do
+            {
+                /*
+                p->prices2[i] = a +
+                // RcTree_GetPrice(enc->high, kLenNumHighBits, i - kLenNumLowSymbols * 2, ProbPrices);
+                LitEnc_GetPrice(probs, i - kLenNumLowSymbols * 2, ProbPrices);
+                 */
+                // UInt32 price = a + RcTree_GetPrice(probs, kLenNumHighBits - 1, sym, ProbPrices);
+                unsigned sym = --i + (1 << (kLenNumHighBits - 1));
+                UInt32 price = b;
+                do
+                {
+                    unsigned bit = sym & 1;
+                    sym >>= 1;
+                    price += GET_PRICEa(probs[sym], bit);
+                }
+                while (sym >= 2);
+
+                {
+                    unsigned prob = probs[(size_t) i + (1 << (kLenNumHighBits - 1))];
+                    prices[(size_t) i * 2 ] = price + GET_PRICEa_0(prob);
+                    prices[(size_t) i * 2 + 1] = price + GET_PRICEa_1(prob);
+                }
+            }
+            while (i);
+
+            {
+                unsigned posState;
+                size_t num = (p->tableSize - kLenNumLowSymbols * 2) * sizeof (p->prices[0][0]);
+                for (posState = 1; posState < numPosStates; posState++)
+                    memcpy(p->prices[posState] + kLenNumLowSymbols * 2, p->prices[0] + kLenNumLowSymbols * 2, num);
+            }
+        }
+    }
+}
+
+/*
+  #ifdef SHOW_STAT
+  g_STAT_OFFSET += num;
+  printf("\n MovePos %u", num);
+  #endif
+ */
+
+#define MOVE_POS(p, num) { \
+    p->additionalOffset += (num); \
+    p->matchFinder.Skip(p->matchFinderObj, (UInt32)(num)); }
+
+static unsigned ReadMatchDistances(CLzmaEnc *p, unsigned *numPairsRes)
+{
+    unsigned numPairs;
+
+    p->additionalOffset++;
+    p->numAvail = p->matchFinder.GetNumAvailableBytes(p->matchFinderObj);
+    numPairs = p->matchFinder.GetMatches(p->matchFinderObj, p->matches);
+    *numPairsRes = numPairs;
+
+#ifdef SHOW_STAT
+    printf("\n i = %u numPairs = %u    ", g_STAT_OFFSET, numPairs / 2);
+    g_STAT_OFFSET++;
+    {
+        unsigned i;
+        for (i = 0; i < numPairs; i += 2)
+            printf("%2u %6u   | ", p->matches[i], p->matches[i + 1]);
+    }
+#endif
+
+    if (numPairs == 0)
+        return 0;
+    {
+        unsigned len = p->matches[(size_t) numPairs - 2];
+        if (len != p->numFastBytes)
+            return len;
+        {
+            UInt32 numAvail = p->numAvail;
+            if (numAvail > LZMA_MATCH_LEN_MAX)
+                numAvail = LZMA_MATCH_LEN_MAX;
+            {
+                const Byte *p1 = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;
+                const Byte *p2 = p1 + len;
+                ptrdiff_t dif = (ptrdiff_t) - 1 - p->matches[(size_t) numPairs - 1];
+                const Byte *lim = p1 + numAvail;
+                for (; p2 != lim && *p2 == p2[dif]; p2++)
+                {
+                }
+                return (unsigned) (p2 - p1);
+            }
+        }
+    }
+}
+
+#define MARK_LIT ((UInt32)(Int32)-1)
+
+#define MakeAs_Lit(p)       { (p)->dist = MARK_LIT; (p)->extra = 0; }
+#define MakeAs_ShortRep(p)  { (p)->dist = 0; (p)->extra = 0; }
+#define IsShortRep(p)       ((p)->dist == 0)
+
+
+#define GetPrice_ShortRep(p, state, posState) \
+  ( GET_PRICE_0(p->isRepG0[state]) + GET_PRICE_0(p->isRep0Long[state][posState]))
+
+#define GetPrice_Rep_0(p, state, posState) ( \
+    GET_PRICE_1(p->isMatch[state][posState]) \
+  + GET_PRICE_1(p->isRep0Long[state][posState])) \
+  + GET_PRICE_1(p->isRep[state]) \
+  + GET_PRICE_0(p->isRepG0[state])
+
+MY_FORCE_INLINE
+static UInt32 GetPrice_PureRep(const CLzmaEnc *p, unsigned repIndex, size_t state, size_t posState)
+{
+    UInt32 price;
+    UInt32 prob = p->isRepG0[state];
+    if (repIndex == 0)
+    {
+        price = GET_PRICE_0(prob);
+        price += GET_PRICE_1(p->isRep0Long[state][posState]);
+    }
+    else
+    {
+        price = GET_PRICE_1(prob);
+        prob = p->isRepG1[state];
+        if (repIndex == 1)
+            price += GET_PRICE_0(prob);
+        else
+        {
+            price += GET_PRICE_1(prob);
+            price += GET_PRICE(p->isRepG2[state], repIndex - 2);
+        }
+    }
+    return price;
+}
+
+static unsigned Backward(CLzmaEnc *p, unsigned cur)
+{
+    unsigned wr = cur + 1;
+    p->optEnd = wr;
+
+    for (;;)
+    {
+        UInt32 dist = p->opt[cur].dist;
+        unsigned len = (unsigned) p->opt[cur].len;
+        unsigned extra = (unsigned) p->opt[cur].extra;
+        cur -= len;
+
+        if (extra)
+        {
+            wr--;
+            p->opt[wr].len = (UInt32) len;
+            cur -= extra;
+            len = extra;
+            if (extra == 1)
+            {
+                p->opt[wr].dist = dist;
+                dist = MARK_LIT;
+            }
+            else
+            {
+                p->opt[wr].dist = 0;
+                len--;
+                wr--;
+                p->opt[wr].dist = MARK_LIT;
+                p->opt[wr].len = 1;
+            }
+        }
+
+        if (cur == 0)
+        {
+            p->backRes = dist;
+            p->optCur = wr;
+            return len;
+        }
+
+        wr--;
+        p->opt[wr].dist = dist;
+        p->opt[wr].len = (UInt32) len;
+    }
+}
+
+
+
+#define LIT_PROBS(pos, prevByte) \
+  (p->litProbs + (UInt32)3 * (((((pos) << 8) + (prevByte)) & p->lpMask) << p->lc))
+
+static unsigned GetOptimum(CLzmaEnc *p, UInt32 position)
+{
+    unsigned last, cur;
+    UInt32 reps[LZMA_NUM_REPS];
+    unsigned repLens[LZMA_NUM_REPS];
+    UInt32 *matches;
+
+    {
+        UInt32 numAvail;
+        unsigned numPairs, mainLen, repMaxIndex, i, posState;
+        UInt32 matchPrice, repMatchPrice;
+        const Byte *data;
+        Byte curByte, matchByte;
+
+        p->optCur = p->optEnd = 0;
+
+        if (p->additionalOffset == 0)
+            mainLen = ReadMatchDistances(p, &numPairs);
+        else
+        {
+            mainLen = p->longestMatchLen;
+            numPairs = p->numPairs;
+        }
+
+        numAvail = p->numAvail;
+        if (numAvail < 2)
+        {
+            p->backRes = MARK_LIT;
+            return 1;
+        }
+        if (numAvail > LZMA_MATCH_LEN_MAX)
+            numAvail = LZMA_MATCH_LEN_MAX;
+
+        data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;
+        repMaxIndex = 0;
+
+        for (i = 0; i < LZMA_NUM_REPS; i++)
+        {
+            unsigned len;
+            const Byte *data2;
+            reps[i] = p->reps[i];
+            data2 = data - reps[i];
+            if (data[0] != data2[0] || data[1] != data2[1])
+            {
+                repLens[i] = 0;
+                continue;
+            }
+            for (len = 2; len < numAvail && data[len] == data2[len]; len++)
+            {
+            }
+            repLens[i] = len;
+            if (len > repLens[repMaxIndex])
+                repMaxIndex = i;
+        }
+
+        if (repLens[repMaxIndex] >= p->numFastBytes)
+        {
+            unsigned len;
+            p->backRes = (UInt32) repMaxIndex;
+            len = repLens[repMaxIndex];
+            MOVE_POS(p, len - 1)
+            return len;
+        }
+
+        matches = p->matches;
+
+        if (mainLen >= p->numFastBytes)
+        {
+            p->backRes = matches[(size_t) numPairs - 1] + LZMA_NUM_REPS;
+            MOVE_POS(p, mainLen - 1)
+            return mainLen;
+        }
+
+        curByte = *data;
+        matchByte = *(data - reps[0]);
+
+        last = repLens[repMaxIndex];
+        if (last <= mainLen)
+            last = mainLen;
+
+        if (last < 2 && curByte != matchByte)
+        {
+            p->backRes = MARK_LIT;
+            return 1;
+        }
+
+        p->opt[0].state = (CState) p->state;
+
+        posState = (position & p->pbMask);
+
+        {
+            const CLzmaProb *probs = LIT_PROBS(position, *(data - 1));
+            p->opt[1].price = GET_PRICE_0(p->isMatch[p->state][posState]) +
+                    (!IsLitState(p->state) ?
+                    LitEnc_Matched_GetPrice(probs, curByte, matchByte, p->ProbPrices) :
+                    LitEnc_GetPrice(probs, curByte, p->ProbPrices));
+        }
+
+        MakeAs_Lit(&p->opt[1]);
+
+        matchPrice = GET_PRICE_1(p->isMatch[p->state][posState]);
+        repMatchPrice = matchPrice + GET_PRICE_1(p->isRep[p->state]);
+
+        // 18.06
+        if (matchByte == curByte && repLens[0] == 0)
+        {
+            UInt32 shortRepPrice = repMatchPrice + GetPrice_ShortRep(p, p->state, posState);
+            if (shortRepPrice < p->opt[1].price)
+            {
+                p->opt[1].price = shortRepPrice;
+                MakeAs_ShortRep(&p->opt[1]);
+            }
+            if (last < 2)
+            {
+                p->backRes = p->opt[1].dist;
+                return 1;
+            }
+        }
+
+        p->opt[1].len = 1;
+
+        p->opt[0].reps[0] = reps[0];
+        p->opt[0].reps[1] = reps[1];
+        p->opt[0].reps[2] = reps[2];
+        p->opt[0].reps[3] = reps[3];
+
+        // ---------- REP ----------
+
+        for (i = 0; i < LZMA_NUM_REPS; i++)
+        {
+            unsigned repLen = repLens[i];
+            UInt32 price;
+            if (repLen < 2)
+                continue;
+            price = repMatchPrice + GetPrice_PureRep(p, i, p->state, posState);
+            do
+            {
+                UInt32 price2 = price + GET_PRICE_LEN(&p->repLenEnc, posState, repLen);
+                COptimal *opt = &p->opt[repLen];
+                if (price2 < opt->price)
+                {
+                    opt->price = price2;
+                    opt->len = (UInt32) repLen;
+                    opt->dist = (UInt32) i;
+                    opt->extra = 0;
+                }
+            }
+            while (--repLen >= 2);
+        }
+
+
+        // ---------- MATCH ----------
+        {
+            unsigned len = repLens[0] + 1;
+            if (len <= mainLen)
+            {
+                unsigned offs = 0;
+                UInt32 normalMatchPrice = matchPrice + GET_PRICE_0(p->isRep[p->state]);
+
+                if (len < 2)
+                    len = 2;
+                else
+                    while (len > matches[offs])
+                        offs += 2;
+
+                for (;; len++)
+                {
+                    COptimal *opt;
+                    UInt32 dist = matches[(size_t) offs + 1];
+                    UInt32 price = normalMatchPrice + GET_PRICE_LEN(&p->lenEnc, posState, len);
+                    unsigned lenToPosState = GetLenToPosState(len);
+
+                    if (dist < kNumFullDistances)
+                        price += p->distancesPrices[lenToPosState][dist & (kNumFullDistances - 1)];
+                    else
+                    {
+                        unsigned slot;
+                        GetPosSlot2(dist, slot);
+                        price += p->alignPrices[dist & kAlignMask];
+                        price += p->posSlotPrices[lenToPosState][slot];
+                    }
+
+                    opt = &p->opt[len];
+
+                    if (price < opt->price)
+                    {
+                        opt->price = price;
+                        opt->len = (UInt32) len;
+                        opt->dist = dist + LZMA_NUM_REPS;
+                        opt->extra = 0;
+                    }
+
+                    if (len == matches[offs])
+                    {
+                        offs += 2;
+                        if (offs == numPairs)
+                            break;
+                    }
+                }
+            }
+        }
+
+
+        cur = 0;
+
+#ifdef SHOW_STAT2
+        /* if (position >= 0) */
+        {
+            unsigned i;
+            printf("\n pos = %4X", position);
+            for (i = cur; i <= last; i++)
+                printf("\nprice[%4X] = %u", position - cur + i, p->opt[i].price);
+        }
+#endif
+    }
+
+
+
+    // ---------- Optimal Parsing ----------
+
+    for (;;)
+    {
+        unsigned numAvail;
+        UInt32 numAvailFull;
+        unsigned newLen, numPairs, prev, state, posState, startLen;
+        UInt32 litPrice, matchPrice, repMatchPrice;
+        BoolInt nextIsLit;
+        Byte curByte, matchByte;
+        const Byte *data;
+        COptimal *curOpt, *nextOpt;
+
+        if (++cur == last)
+            break;
+
+        // 18.06
+        if (cur >= kNumOpts - 64)
+        {
+            unsigned j, best;
+            UInt32 price = p->opt[cur].price;
+            best = cur;
+            for (j = cur + 1; j <= last; j++)
+            {
+                UInt32 price2 = p->opt[j].price;
+                if (price >= price2)
+                {
+                    price = price2;
+                    best = j;
+                }
+            }
+            {
+                unsigned delta = best - cur;
+                if (delta != 0)
+                {
+                    MOVE_POS(p, delta);
+                }
+            }
+            cur = best;
+            break;
+        }
+
+        newLen = ReadMatchDistances(p, &numPairs);
+
+        if (newLen >= p->numFastBytes)
+        {
+            p->numPairs = numPairs;
+            p->longestMatchLen = newLen;
+            break;
+        }
+
+        curOpt = &p->opt[cur];
+
+        position++;
+
+        // we need that check here, if skip_items in p->opt are possible
+        /*
+        if (curOpt->price >= kInfinityPrice)
+          continue;
+         */
+
+        prev = cur - curOpt->len;
+
+        if (curOpt->len == 1)
+        {
+            state = (unsigned) p->opt[prev].state;
+            if (IsShortRep(curOpt))
+                state = kShortRepNextStates[state];
+            else
+                state = kLiteralNextStates[state];
+        }
+        else
+        {
+            const COptimal *prevOpt;
+            UInt32 b0;
+            UInt32 dist = curOpt->dist;
+
+            if (curOpt->extra)
+            {
+                prev -= (unsigned) curOpt->extra;
+                state = kState_RepAfterLit;
+                if (curOpt->extra == 1)
+                    state = (dist < LZMA_NUM_REPS ? kState_RepAfterLit : kState_MatchAfterLit);
+            }
+            else
+            {
+                state = (unsigned) p->opt[prev].state;
+                if (dist < LZMA_NUM_REPS)
+                    state = kRepNextStates[state];
+                else
+                    state = kMatchNextStates[state];
+            }
+
+            prevOpt = &p->opt[prev];
+            b0 = prevOpt->reps[0];
+
+            if (dist < LZMA_NUM_REPS)
+            {
+                if (dist == 0)
+                {
+                    reps[0] = b0;
+                    reps[1] = prevOpt->reps[1];
+                    reps[2] = prevOpt->reps[2];
+                    reps[3] = prevOpt->reps[3];
+                }
+                else
+                {
+                    reps[1] = b0;
+                    b0 = prevOpt->reps[1];
+                    if (dist == 1)
+                    {
+                        reps[0] = b0;
+                        reps[2] = prevOpt->reps[2];
+                        reps[3] = prevOpt->reps[3];
+                    }
+                    else
+                    {
+                        reps[2] = b0;
+                        reps[0] = prevOpt->reps[dist];
+                        reps[3] = prevOpt->reps[dist ^ 1];
+                    }
+                }
+            }
+            else
+            {
+                reps[0] = (dist - LZMA_NUM_REPS + 1);
+                reps[1] = b0;
+                reps[2] = prevOpt->reps[1];
+                reps[3] = prevOpt->reps[2];
+            }
+        }
+
+        curOpt->state = (CState) state;
+        curOpt->reps[0] = reps[0];
+        curOpt->reps[1] = reps[1];
+        curOpt->reps[2] = reps[2];
+        curOpt->reps[3] = reps[3];
+
+        data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;
+        curByte = *data;
+        matchByte = *(data - reps[0]);
+
+        posState = (position & p->pbMask);
+
+        /*
+        The order of Price checks:
+           <  LIT
+           <= SHORT_REP
+           <  LIT : REP_0
+           <  REP    [ : LIT : REP_0 ]
+           <  MATCH  [ : LIT : REP_0 ]
+         */
+
+        {
+            UInt32 curPrice = curOpt->price;
+            unsigned prob = p->isMatch[state][posState];
+            matchPrice = curPrice + GET_PRICE_1(prob);
+            litPrice = curPrice + GET_PRICE_0(prob);
+        }
+
+        nextOpt = &p->opt[(size_t) cur + 1];
+        nextIsLit = False;
+
+        // here we can allow skip_items in p->opt, if we don't check (nextOpt->price < kInfinityPrice)
+        // 18.new.06
+        if ((nextOpt->price < kInfinityPrice
+                // && !IsLitState(state)
+                && matchByte == curByte)
+                || litPrice > nextOpt->price
+                )
+            litPrice = 0;
+        else
+        {
+            const CLzmaProb *probs = LIT_PROBS(position, *(data - 1));
+            litPrice += (!IsLitState(state) ?
+                    LitEnc_Matched_GetPrice(probs, curByte, matchByte, p->ProbPrices) :
+                    LitEnc_GetPrice(probs, curByte, p->ProbPrices));
+
+            if (litPrice < nextOpt->price)
+            {
+                nextOpt->price = litPrice;
+                nextOpt->len = 1;
+                MakeAs_Lit(nextOpt);
+                nextIsLit = True;
+            }
+        }
+
+        repMatchPrice = matchPrice + GET_PRICE_1(p->isRep[state]);
+
+        numAvailFull = p->numAvail;
+        {
+            unsigned temp = kNumOpts - 1 - cur;
+            if (numAvailFull > temp)
+                numAvailFull = (UInt32) temp;
+        }
+
+        // 18.06
+        // ---------- SHORT_REP ----------
+        if (IsLitState(state)) // 18.new
+            if (matchByte == curByte)
+                if (repMatchPrice < nextOpt->price) // 18.new
+                    // if (numAvailFull < 2 || data[1] != *(data - reps[0] + 1))
+                    if (
+                            // nextOpt->price >= kInfinityPrice ||
+                            nextOpt->len < 2 // we can check nextOpt->len, if skip items are not allowed in p->opt
+                            || (nextOpt->dist != 0
+                            // && nextOpt->extra <= 1 // 17.old
+                            )
+                            )
+                    {
+                        UInt32 shortRepPrice = repMatchPrice + GetPrice_ShortRep(p, state, posState);
+                        // if (shortRepPrice <= nextOpt->price) // 17.old
+                        if (shortRepPrice < nextOpt->price) // 18.new
+                        {
+                            nextOpt->price = shortRepPrice;
+                            nextOpt->len = 1;
+                            MakeAs_ShortRep(nextOpt);
+                            nextIsLit = False;
+                        }
+                    }
+
+        if (numAvailFull < 2)
+            continue;
+        numAvail = (numAvailFull <= p->numFastBytes ? numAvailFull : p->numFastBytes);
+
+        // numAvail <= p->numFastBytes
+
+        // ---------- LIT : REP_0 ----------
+
+        if (!nextIsLit
+                && litPrice != 0 // 18.new
+                && matchByte != curByte
+                && numAvailFull > 2)
+        {
+            const Byte *data2 = data - reps[0];
+            if (data[1] == data2[1] && data[2] == data2[2])
+            {
+                unsigned len;
+                unsigned limit = p->numFastBytes + 1;
+                if (limit > numAvailFull)
+                    limit = numAvailFull;
+                for (len = 3; len < limit && data[len] == data2[len]; len++)
+                {
+                }
+
+                {
+                    unsigned state2 = kLiteralNextStates[state];
+                    unsigned posState2 = (position + 1) & p->pbMask;
+                    UInt32 price = litPrice + GetPrice_Rep_0(p, state2, posState2);
+                    {
+                        unsigned offset = cur + len;
+
+                        if (last < offset)
+                            last = offset;
+
+                        // do
+                        {
+                            UInt32 price2;
+                            COptimal *opt;
+                            len--;
+                            // price2 = price + GetPrice_Len_Rep_0(p, len, state2, posState2);
+                            price2 = price + GET_PRICE_LEN(&p->repLenEnc, posState2, len);
+
+                            opt = &p->opt[offset];
+                            // offset--;
+                            if (price2 < opt->price)
+                            {
+                                opt->price = price2;
+                                opt->len = (UInt32) len;
+                                opt->dist = 0;
+                                opt->extra = 1;
+                            }
+                        }
+                        // while (len >= 3);
+                    }
+                }
+            }
+        }
+
+        startLen = 2; /* speed optimization */
+
+        {
+            // ---------- REP ----------
+            unsigned repIndex = 0; // 17.old
+            // unsigned repIndex = IsLitState(state) ? 0 : 1; // 18.notused
+            for (; repIndex < LZMA_NUM_REPS; repIndex++)
+            {
+                unsigned len;
+                UInt32 price;
+                const Byte *data2 = data - reps[repIndex];
+                if (data[0] != data2[0] || data[1] != data2[1])
+                    continue;
+
+                for (len = 2; len < numAvail && data[len] == data2[len]; len++)
+                {
+                }
+
+                // if (len < startLen) continue; // 18.new: speed optimization
+
+                {
+                    unsigned offset = cur + len;
+                    if (last < offset)
+                        last = offset;
+                }
+                {
+                    unsigned len2 = len;
+                    price = repMatchPrice + GetPrice_PureRep(p, repIndex, state, posState);
+                    do
+                    {
+                        UInt32 price2 = price + GET_PRICE_LEN(&p->repLenEnc, posState, len2);
+                        COptimal *opt = &p->opt[cur + len2];
+                        if (price2 < opt->price)
+                        {
+                            opt->price = price2;
+                            opt->len = (UInt32) len2;
+                            opt->dist = (UInt32) repIndex;
+                            opt->extra = 0;
+                        }
+                    }
+                    while (--len2 >= 2);
+                }
+
+                if (repIndex == 0) startLen = len + 1; // 17.old
+                // startLen = len + 1; // 18.new
+
+                /* if (_maxMode) */
+                {
+                    // ---------- REP : LIT : REP_0 ----------
+                    // numFastBytes + 1 + numFastBytes
+
+                    unsigned len2 = len + 1;
+                    unsigned limit = len2 + p->numFastBytes;
+                    if (limit > numAvailFull)
+                        limit = numAvailFull;
+
+                    len2 += 2;
+                    if (len2 <= limit)
+                        if (data[len2 - 2] == data2[len2 - 2])
+                            if (data[len2 - 1] == data2[len2 - 1])
+                            {
+                                unsigned state2 = kRepNextStates[state];
+                                unsigned posState2 = (position + len) & p->pbMask;
+                                price += GET_PRICE_LEN(&p->repLenEnc, posState, len)
+                                        + GET_PRICE_0(p->isMatch[state2][posState2])
+                                        + LitEnc_Matched_GetPrice(LIT_PROBS(position + len, data[(size_t) len - 1]),
+                                                                  data[len], data2[len], p->ProbPrices);
+
+                                // state2 = kLiteralNextStates[state2];
+                                state2 = kState_LitAfterRep;
+                                posState2 = (posState2 + 1) & p->pbMask;
+
+
+                                price += GetPrice_Rep_0(p, state2, posState2);
+
+                                for (; len2 < limit && data[len2] == data2[len2]; len2++)
+                                {
+                                }
+
+                                len2 -= len;
+                                // if (len2 >= 3)
+                                {
+                                    {
+                                        unsigned offset = cur + len + len2;
+
+                                        if (last < offset)
+                                            last = offset;
+                                        // do
+                                        {
+                                            UInt32 price2;
+                                            COptimal *opt;
+                                            len2--;
+                                            // price2 = price + GetPrice_Len_Rep_0(p, len2, state2, posState2);
+                                            price2 = price + GET_PRICE_LEN(&p->repLenEnc, posState2, len2);
+
+                                            opt = &p->opt[offset];
+                                            // offset--;
+                                            if (price2 < opt->price)
+                                            {
+                                                opt->price = price2;
+                                                opt->len = (UInt32) len2;
+                                                opt->extra = (CExtra) (len + 1);
+                                                opt->dist = (UInt32) repIndex;
+                                            }
+                                        }
+                                        // while (len2 >= 3);
+                                    }
+                                }
+                            }
+                }
+            }
+        }
+
+
+        // ---------- MATCH ----------
+        /* for (unsigned len = 2; len <= newLen; len++) */
+        if (newLen > numAvail)
+        {
+            newLen = numAvail;
+            for (numPairs = 0; newLen > matches[numPairs]; numPairs += 2);
+            matches[numPairs] = (UInt32) newLen;
+            numPairs += 2;
+        }
+
+        // startLen = 2; /* speed optimization */
+
+        if (newLen >= startLen)
+        {
+            UInt32 normalMatchPrice = matchPrice + GET_PRICE_0(p->isRep[state]);
+            UInt32 dist;
+            unsigned offs, posSlot, len;
+
+            {
+                unsigned offset = cur + newLen;
+                if (last < offset)
+                    last = offset;
+            }
+
+            offs = 0;
+            while (startLen > matches[offs])
+                offs += 2;
+            dist = matches[(size_t) offs + 1];
+
+            // if (dist >= kNumFullDistances)
+            GetPosSlot2(dist, posSlot);
+
+            for (len = /*2*/ startLen;; len++)
+            {
+                UInt32 price = normalMatchPrice + GET_PRICE_LEN(&p->lenEnc, posState, len);
+                {
+                    COptimal *opt;
+                    unsigned lenNorm = len - 2;
+                    lenNorm = GetLenToPosState2(lenNorm);
+                    if (dist < kNumFullDistances)
+                        price += p->distancesPrices[lenNorm][dist & (kNumFullDistances - 1)];
+                    else
+                        price += p->posSlotPrices[lenNorm][posSlot] + p->alignPrices[dist & kAlignMask];
+
+                    opt = &p->opt[cur + len];
+                    if (price < opt->price)
+                    {
+                        opt->price = price;
+                        opt->len = (UInt32) len;
+                        opt->dist = dist + LZMA_NUM_REPS;
+                        opt->extra = 0;
+                    }
+                }
+
+                if (len == matches[offs])
+                {
+                    // if (p->_maxMode) {
+                    // MATCH : LIT : REP_0
+
+                    const Byte *data2 = data - dist - 1;
+                    unsigned len2 = len + 1;
+                    unsigned limit = len2 + p->numFastBytes;
+                    if (limit > numAvailFull)
+                        limit = numAvailFull;
+
+                    len2 += 2;
+                    if (len2 <= limit)
+                        if (data[len2 - 2] == data2[len2 - 2])
+                            if (data[len2 - 1] == data2[len2 - 1])
+                            {
+                                for (; len2 < limit && data[len2] == data2[len2]; len2++)
+                                {
+                                }
+
+                                len2 -= len;
+
+                                // if (len2 >= 3)
+                                {
+                                    unsigned state2 = kMatchNextStates[state];
+                                    unsigned posState2 = (position + len) & p->pbMask;
+                                    unsigned offset;
+                                    price += GET_PRICE_0(p->isMatch[state2][posState2]);
+                                    price += LitEnc_Matched_GetPrice(LIT_PROBS(position + len, data[(size_t) len - 1]),
+                                                                     data[len], data2[len], p->ProbPrices);
+
+                                    // state2 = kLiteralNextStates[state2];
+                                    state2 = kState_LitAfterMatch;
+
+                                    posState2 = (posState2 + 1) & p->pbMask;
+                                    price += GetPrice_Rep_0(p, state2, posState2);
+
+                                    offset = cur + len + len2;
+
+                                    if (last < offset)
+                                        last = offset;
+                                    // do
+                                    {
+                                        UInt32 price2;
+                                        COptimal *opt;
+                                        len2--;
+                                        // price2 = price + GetPrice_Len_Rep_0(p, len2, state2, posState2);
+                                        price2 = price + GET_PRICE_LEN(&p->repLenEnc, posState2, len2);
+                                        opt = &p->opt[offset];
+                                        // offset--;
+                                        if (price2 < opt->price)
+                                        {
+                                            opt->price = price2;
+                                            opt->len = (UInt32) len2;
+                                            opt->extra = (CExtra) (len + 1);
+                                            opt->dist = dist + LZMA_NUM_REPS;
+                                        }
+                                    }
+                                    // while (len2 >= 3);
+                                }
+
+                            }
+
+                    offs += 2;
+                    if (offs == numPairs)
+                        break;
+                    dist = matches[(size_t) offs + 1];
+                    // if (dist >= kNumFullDistances)
+                    GetPosSlot2(dist, posSlot);
+                }
+            }
+        }
+    }
+
+    do
+        p->opt[last].price = kInfinityPrice;
+    while (--last);
+
+    return Backward(p, cur);
+}
+
+
+
+#define ChangePair(smallDist, bigDist) (((bigDist) >> 7) > (smallDist))
+
+static unsigned GetOptimumFast(CLzmaEnc *p)
+{
+    UInt32 numAvail, mainDist;
+    unsigned mainLen, numPairs, repIndex, repLen, i;
+    const Byte *data;
+
+    if (p->additionalOffset == 0)
+        mainLen = ReadMatchDistances(p, &numPairs);
+    else
+    {
+        mainLen = p->longestMatchLen;
+        numPairs = p->numPairs;
+    }
+
+    numAvail = p->numAvail;
+    p->backRes = MARK_LIT;
+    if (numAvail < 2)
+        return 1;
+    // if (mainLen < 2 && p->state == 0) return 1; // 18.06.notused
+    if (numAvail > LZMA_MATCH_LEN_MAX)
+        numAvail = LZMA_MATCH_LEN_MAX;
+    data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;
+    repLen = repIndex = 0;
+
+    for (i = 0; i < LZMA_NUM_REPS; i++)
+    {
+        unsigned len;
+        const Byte *data2 = data - p->reps[i];
+        if (data[0] != data2[0] || data[1] != data2[1])
+            continue;
+        for (len = 2; len < numAvail && data[len] == data2[len]; len++)
+        {
+        }
+        if (len >= p->numFastBytes)
+        {
+            p->backRes = (UInt32) i;
+            MOVE_POS(p, len - 1)
+            return len;
+        }
+        if (len > repLen)
+        {
+            repIndex = i;
+            repLen = len;
+        }
+    }
+
+    if (mainLen >= p->numFastBytes)
+    {
+        p->backRes = p->matches[(size_t) numPairs - 1] + LZMA_NUM_REPS;
+        MOVE_POS(p, mainLen - 1)
+        return mainLen;
+    }
+
+    mainDist = 0; /* for GCC */
+
+    if (mainLen >= 2)
+    {
+        mainDist = p->matches[(size_t) numPairs - 1];
+        while (numPairs > 2)
+        {
+            UInt32 dist2;
+            if (mainLen != p->matches[(size_t) numPairs - 4] + 1)
+                break;
+            dist2 = p->matches[(size_t) numPairs - 3];
+            if (!ChangePair(dist2, mainDist))
+                break;
+            numPairs -= 2;
+            mainLen--;
+            mainDist = dist2;
+        }
+        if (mainLen == 2 && mainDist >= 0x80)
+            mainLen = 1;
+    }
+
+    if (repLen >= 2)
+        if (repLen + 1 >= mainLen
+                || (repLen + 2 >= mainLen && mainDist >= (1 << 9))
+                || (repLen + 3 >= mainLen && mainDist >= (1 << 15)))
+        {
+            p->backRes = (UInt32) repIndex;
+            MOVE_POS(p, repLen - 1)
+            return repLen;
+        }
+
+    if (mainLen < 2 || numAvail <= 2)
+        return 1;
+
+    {
+        unsigned len1 = ReadMatchDistances(p, &p->numPairs);
+        p->longestMatchLen = len1;
+
+        if (len1 >= 2)
+        {
+            UInt32 newDist = p->matches[(size_t) p->numPairs - 1];
+            if ((len1 >= mainLen && newDist < mainDist)
+                    || (len1 == mainLen + 1 && !ChangePair(mainDist, newDist))
+                    || (len1 > mainLen + 1)
+                    || (len1 + 1 >= mainLen && mainLen >= 3 && ChangePair(newDist, mainDist)))
+                return 1;
+        }
+    }
+
+    data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;
+
+    for (i = 0; i < LZMA_NUM_REPS; i++)
+    {
+        unsigned len, limit;
+        const Byte *data2 = data - p->reps[i];
+        if (data[0] != data2[0] || data[1] != data2[1])
+            continue;
+        limit = mainLen - 1;
+        for (len = 2;; len++)
+        {
+            if (len >= limit)
+                return 1;
+            if (data[len] != data2[len])
+                break;
+        }
+    }
+
+    p->backRes = mainDist + LZMA_NUM_REPS;
+    if (mainLen != 2)
+    {
+        MOVE_POS(p, mainLen - 2)
+    }
+    return mainLen;
+}
+
+static void WriteEndMarker(CLzmaEnc *p, unsigned posState)
+{
+    UInt32 range;
+    range = p->rc.range;
+    {
+        UInt32 ttt, newBound;
+        CLzmaProb *prob = &p->isMatch[p->state][posState];
+        RC_BIT_PRE(&p->rc, prob)
+        RC_BIT_1(&p->rc, prob)
+        prob = &p->isRep[p->state];
+        RC_BIT_PRE(&p->rc, prob)
+        RC_BIT_0(&p->rc, prob)
+    }
+    p->state = kMatchNextStates[p->state];
+
+    p->rc.range = range;
+    LenEnc_Encode(&p->lenProbs, &p->rc, 0, posState);
+    range = p->rc.range;
+
+    {
+        // RcTree_Encode_PosSlot(&p->rc, p->posSlotEncoder[0], (1 << kNumPosSlotBits) - 1);
+        CLzmaProb *probs = p->posSlotEncoder[0];
+        unsigned m = 1;
+        do
+        {
+            UInt32 ttt, newBound;
+            RC_BIT_PRE(p, probs + m)
+            RC_BIT_1(&p->rc, probs + m);
+            m = (m << 1) + 1;
+        }
+        while (m < (1 << kNumPosSlotBits));
+    }
+    {
+        // RangeEnc_EncodeDirectBits(&p->rc, ((UInt32)1 << (30 - kNumAlignBits)) - 1, 30 - kNumAlignBits);    UInt32 range = p->range;
+        unsigned numBits = 30 - kNumAlignBits;
+        do
+        {
+            range >>= 1;
+            p->rc.low += range;
+            RC_NORM(&p->rc)
+        }
+        while (--numBits);
+    }
+
+    {
+        // RcTree_ReverseEncode(&p->rc, p->posAlignEncoder, kNumAlignBits, kAlignMask);
+        CLzmaProb *probs = p->posAlignEncoder;
+        unsigned m = 1;
+        do
+        {
+            UInt32 ttt, newBound;
+            RC_BIT_PRE(p, probs + m)
+            RC_BIT_1(&p->rc, probs + m);
+            m = (m << 1) + 1;
+        }
+        while (m < kAlignTableSize);
+    }
+    p->rc.range = range;
+}
+
+static SRes CheckErrors(CLzmaEnc *p)
+{
+    if (p->result != SZ_OK)
+        return p->result;
+    if (p->rc.res != SZ_OK)
+        p->result = SZ_ERROR_WRITE;
+    if (p->matchFinderBase.result != SZ_OK)
+        p->result = SZ_ERROR_READ;
+    if (p->result != SZ_OK)
+        p->finished = True;
+    return p->result;
+}
+
+MY_NO_INLINE static SRes Flush(CLzmaEnc *p, UInt32 nowPos)
+{
+    /* ReleaseMFStream(); */
+    p->finished = True;
+    if (p->writeEndMark)
+        WriteEndMarker(p, nowPos & p->pbMask);
+    RangeEnc_FlushData(&p->rc);
+    RangeEnc_FlushStream(&p->rc);
+    return CheckErrors(p);
+}
+
+MY_NO_INLINE static void FillAlignPrices(CLzmaEnc *p)
+{
+    unsigned i;
+    const CProbPrice *ProbPrices = p->ProbPrices;
+    const CLzmaProb *probs = p->posAlignEncoder;
+    // p->alignPriceCount = 0;
+    for (i = 0; i < kAlignTableSize / 2; i++)
+    {
+        UInt32 price = 0;
+        unsigned sym = i;
+        unsigned m = 1;
+        unsigned bit;
+        UInt32 prob;
+        bit = sym & 1;
+        sym >>= 1;
+        price += GET_PRICEa(probs[m], bit);
+        m = (m << 1) + bit;
+        bit = sym & 1;
+        sym >>= 1;
+        price += GET_PRICEa(probs[m], bit);
+        m = (m << 1) + bit;
+        bit = sym & 1;
+        sym >>= 1;
+        price += GET_PRICEa(probs[m], bit);
+        m = (m << 1) + bit;
+        prob = probs[m];
+        p->alignPrices[i ] = price + GET_PRICEa_0(prob);
+        p->alignPrices[i + 8] = price + GET_PRICEa_1(prob);
+        // p->alignPrices[i] = RcTree_ReverseGetPrice(p->posAlignEncoder, kNumAlignBits, i, p->ProbPrices);
+    }
+}
+
+MY_NO_INLINE static void FillDistancesPrices(CLzmaEnc *p)
+{
+    // int y; for (y = 0; y < 100; y++) {
+
+    UInt32 tempPrices[kNumFullDistances];
+    unsigned i, lps;
+
+    const CProbPrice *ProbPrices = p->ProbPrices;
+    p->matchPriceCount = 0;
+
+    for (i = kStartPosModelIndex / 2; i < kNumFullDistances / 2; i++)
+    {
+        unsigned posSlot = GetPosSlot1(i);
+        unsigned footerBits = (posSlot >> 1) - 1;
+        unsigned base = ((2 | (posSlot & 1)) << footerBits);
+        const CLzmaProb *probs = p->posEncoders + (size_t) base * 2;
+        // tempPrices[i] = RcTree_ReverseGetPrice(p->posEncoders + base, footerBits, i - base, p->ProbPrices);
+        UInt32 price = 0;
+        unsigned m = 1;
+        unsigned sym = i;
+        unsigned offset = (unsigned) 1 << footerBits;
+        base += i;
+
+        if (footerBits)
+            do
+            {
+                unsigned bit = sym & 1;
+                sym >>= 1;
+                price += GET_PRICEa(probs[m], bit);
+                m = (m << 1) + bit;
+            }
+            while (--footerBits);
+
+        {
+            unsigned prob = probs[m];
+            tempPrices[base ] = price + GET_PRICEa_0(prob);
+            tempPrices[base + offset] = price + GET_PRICEa_1(prob);
+        }
+    }
+
+    for (lps = 0; lps < kNumLenToPosStates; lps++)
+    {
+        unsigned slot;
+        unsigned distTableSize2 = (p->distTableSize + 1) >> 1;
+        UInt32 *posSlotPrices = p->posSlotPrices[lps];
+        const CLzmaProb *probs = p->posSlotEncoder[lps];
+
+        for (slot = 0; slot < distTableSize2; slot++)
+        {
+            // posSlotPrices[slot] = RcTree_GetPrice(encoder, kNumPosSlotBits, slot, p->ProbPrices);
+            UInt32 price;
+            unsigned bit;
+            unsigned sym = slot + (1 << (kNumPosSlotBits - 1));
+            unsigned prob;
+            bit = sym & 1;
+            sym >>= 1;
+            price = GET_PRICEa(probs[sym], bit);
+            bit = sym & 1;
+            sym >>= 1;
+            price += GET_PRICEa(probs[sym], bit);
+            bit = sym & 1;
+            sym >>= 1;
+            price += GET_PRICEa(probs[sym], bit);
+            bit = sym & 1;
+            sym >>= 1;
+            price += GET_PRICEa(probs[sym], bit);
+            bit = sym & 1;
+            sym >>= 1;
+            price += GET_PRICEa(probs[sym], bit);
+            prob = probs[(size_t) slot + (1 << (kNumPosSlotBits - 1))];
+            posSlotPrices[(size_t) slot * 2 ] = price + GET_PRICEa_0(prob);
+            posSlotPrices[(size_t) slot * 2 + 1] = price + GET_PRICEa_1(prob);
+        }
+
+        {
+            UInt32 delta = ((UInt32) ((kEndPosModelIndex / 2 - 1) - kNumAlignBits) << kNumBitPriceShiftBits);
+            for (slot = kEndPosModelIndex / 2; slot < distTableSize2; slot++)
+            {
+                posSlotPrices[(size_t) slot * 2 ] += delta;
+                posSlotPrices[(size_t) slot * 2 + 1] += delta;
+                delta += ((UInt32) 1 << kNumBitPriceShiftBits);
+            }
+        }
+
+        {
+            UInt32 *dp = p->distancesPrices[lps];
+
+            dp[0] = posSlotPrices[0];
+            dp[1] = posSlotPrices[1];
+            dp[2] = posSlotPrices[2];
+            dp[3] = posSlotPrices[3];
+
+            for (i = 4; i < kNumFullDistances; i += 2)
+            {
+                UInt32 slotPrice = posSlotPrices[GetPosSlot1(i)];
+                dp[i ] = slotPrice + tempPrices[i];
+                dp[i + 1] = slotPrice + tempPrices[i + 1];
+            }
+        }
+    }
+    // }
+}
+
+void LzmaEnc_Construct(CLzmaEnc *p)
+{
+    RangeEnc_Construct(&p->rc);
+    MatchFinder_Construct(&p->matchFinderBase);
+
+#ifndef _7ZIP_ST
+    MatchFinderMt_Construct(&p->matchFinderMt);
+    p->matchFinderMt.MatchFinder = &p->matchFinderBase;
+#endif
+
+    {
+        CLzmaEncProps props;
+        LzmaEncProps_Init(&props);
+        LzmaEnc_SetProps(p, &props);
+    }
+
+#ifndef LZMA_LOG_BSR
+    LzmaEnc_FastPosInit(p->g_FastPos);
+#endif
+
+    LzmaEnc_InitPriceTables(p->ProbPrices);
+    p->litProbs = NULL;
+    p->saveState.litProbs = NULL;
+
+}
+
+CLzmaEncHandle LzmaEnc_Create(ISzAllocPtr alloc)
+{
+    void *p;
+    p = ISzAlloc_Alloc(alloc, sizeof (CLzmaEnc));
+    if (p)
+        LzmaEnc_Construct((CLzmaEnc *) p);
+    return p;
+}
+
+void LzmaEnc_FreeLits(CLzmaEnc *p, ISzAllocPtr alloc)
+{
+    ISzAlloc_Free(alloc, p->litProbs);
+    ISzAlloc_Free(alloc, p->saveState.litProbs);
+    p->litProbs = NULL;
+    p->saveState.litProbs = NULL;
+}
+
+void LzmaEnc_Destruct(CLzmaEnc *p, ISzAllocPtr alloc, ISzAllocPtr allocBig)
+{
+#ifndef _7ZIP_ST
+    MatchFinderMt_Destruct(&p->matchFinderMt, allocBig);
+#endif
+
+    MatchFinder_Free(&p->matchFinderBase, allocBig);
+    LzmaEnc_FreeLits(p, alloc);
+    RangeEnc_Free(&p->rc, alloc);
+}
+
+void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAllocPtr alloc, ISzAllocPtr allocBig)
+{
+    LzmaEnc_Destruct((CLzmaEnc *) p, alloc, allocBig);
+    ISzAlloc_Free(alloc, p);
+}
+
+static SRes LzmaEnc_CodeOneBlock(CLzmaEnc *p, UInt32 maxPackSize, UInt32 maxUnpackSize)
+{
+    UInt32 nowPos32, startPos32;
+    if (p->needInit)
+    {
+        p->matchFinder.Init(p->matchFinderObj);
+        p->needInit = 0;
+    }
+
+    if (p->finished)
+        return p->result;
+    RINOK(CheckErrors(p));
+
+    nowPos32 = (UInt32) p->nowPos64;
+    startPos32 = nowPos32;
+
+    if (p->nowPos64 == 0)
+    {
+        unsigned numPairs;
+        Byte curByte;
+        if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) == 0)
+            return Flush(p, nowPos32);
+        ReadMatchDistances(p, &numPairs);
+        RangeEnc_EncodeBit_0(&p->rc, &p->isMatch[kState_Start][0]);
+        // p->state = kLiteralNextStates[p->state];
+        curByte = *(p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset);
+        LitEnc_Encode(&p->rc, p->litProbs, curByte);
+        p->additionalOffset--;
+        nowPos32++;
+    }
+
+    if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) != 0)
+
+        for (;;)
+        {
+            UInt32 dist;
+            unsigned len, posState;
+            UInt32 range, ttt, newBound;
+            CLzmaProb *probs;
+
+            if (p->fastMode)
+                len = GetOptimumFast(p);
+            else
+            {
+                unsigned oci = p->optCur;
+                if (p->optEnd == oci)
+                    len = GetOptimum(p, nowPos32);
+                else
+                {
+                    const COptimal *opt = &p->opt[oci];
+                    len = opt->len;
+                    p->backRes = opt->dist;
+                    p->optCur = oci + 1;
+                }
+            }
+
+            posState = (unsigned) nowPos32 & p->pbMask;
+            range = p->rc.range;
+            probs = &p->isMatch[p->state][posState];
+
+            RC_BIT_PRE(&p->rc, probs)
+
+            dist = p->backRes;
+
+#ifdef SHOW_STAT2
+            printf("\n pos = %6X, len = %3u  pos = %6u", nowPos32, len, dist);
+#endif
+
+            if (dist == MARK_LIT)
+            {
+                Byte curByte;
+                const Byte *data;
+                unsigned state;
+
+                RC_BIT_0(&p->rc, probs);
+                p->rc.range = range;
+                data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset;
+                probs = LIT_PROBS(nowPos32, *(data - 1));
+                curByte = *data;
+                state = p->state;
+                p->state = kLiteralNextStates[state];
+                if (IsLitState(state))
+                    LitEnc_Encode(&p->rc, probs, curByte);
+                else
+                    LitEnc_EncodeMatched(&p->rc, probs, curByte, *(data - p->reps[0]));
+            }
+            else
+            {
+                RC_BIT_1(&p->rc, probs);
+                probs = &p->isRep[p->state];
+                RC_BIT_PRE(&p->rc, probs)
+
+                if (dist < LZMA_NUM_REPS)
+                {
+                    RC_BIT_1(&p->rc, probs);
+                    probs = &p->isRepG0[p->state];
+                    RC_BIT_PRE(&p->rc, probs)
+                    if (dist == 0)
+                    {
+                        RC_BIT_0(&p->rc, probs);
+                        probs = &p->isRep0Long[p->state][posState];
+                        RC_BIT_PRE(&p->rc, probs)
+                        if (len != 1)
+                        {
+                            RC_BIT_1_BASE(&p->rc, probs);
+                        }
+                        else
+                        {
+                            RC_BIT_0_BASE(&p->rc, probs);
+                            p->state = kShortRepNextStates[p->state];
+                        }
+                    }
+                    else
+                    {
+                        RC_BIT_1(&p->rc, probs);
+                        probs = &p->isRepG1[p->state];
+                        RC_BIT_PRE(&p->rc, probs)
+                        if (dist == 1)
+                        {
+                            RC_BIT_0_BASE(&p->rc, probs);
+                            dist = p->reps[1];
+                        }
+                        else
+                        {
+                            RC_BIT_1(&p->rc, probs);
+                            probs = &p->isRepG2[p->state];
+                            RC_BIT_PRE(&p->rc, probs)
+                            if (dist == 2)
+                            {
+                                RC_BIT_0_BASE(&p->rc, probs);
+                                dist = p->reps[2];
+                            }
+                            else
+                            {
+                                RC_BIT_1_BASE(&p->rc, probs);
+                                dist = p->reps[3];
+                                p->reps[3] = p->reps[2];
+                            }
+                            p->reps[2] = p->reps[1];
+                        }
+                        p->reps[1] = p->reps[0];
+                        p->reps[0] = dist;
+                    }
+
+                    RC_NORM(&p->rc)
+
+                    p->rc.range = range;
+
+                    if (len != 1)
+                    {
+                        LenEnc_Encode(&p->repLenProbs, &p->rc, len - LZMA_MATCH_LEN_MIN, posState);
+                        --p->repLenEncCounter;
+                        p->state = kRepNextStates[p->state];
+                    }
+                }
+                else
+                {
+                    unsigned posSlot;
+                    RC_BIT_0(&p->rc, probs);
+                    p->rc.range = range;
+                    p->state = kMatchNextStates[p->state];
+
+                    LenEnc_Encode(&p->lenProbs, &p->rc, len - LZMA_MATCH_LEN_MIN, posState);
+                    // --p->lenEnc.counter;
+
+                    dist -= LZMA_NUM_REPS;
+                    p->reps[3] = p->reps[2];
+                    p->reps[2] = p->reps[1];
+                    p->reps[1] = p->reps[0];
+                    p->reps[0] = dist + 1;
+
+                    p->matchPriceCount++;
+                    GetPosSlot(dist, posSlot);
+                    // RcTree_Encode_PosSlot(&p->rc, p->posSlotEncoder[GetLenToPosState(len)], posSlot);
+                    {
+                        UInt32 sym = (UInt32) posSlot + (1 << kNumPosSlotBits);
+                        range = p->rc.range;
+                        probs = p->posSlotEncoder[GetLenToPosState(len)];
+                        do
+                        {
+                            CLzmaProb *prob = probs + (sym >> kNumPosSlotBits);
+                            UInt32 bit = (sym >> (kNumPosSlotBits - 1)) & 1;
+                            sym <<= 1;
+                            RC_BIT(&p->rc, prob, bit);
+                        }
+                        while (sym < (1 << kNumPosSlotBits * 2));
+                        p->rc.range = range;
+                    }
+
+                    if (dist >= kStartPosModelIndex)
+                    {
+                        unsigned footerBits = ((posSlot >> 1) - 1);
+
+                        if (dist < kNumFullDistances)
+                        {
+                            unsigned base = ((2 | (posSlot & 1)) << footerBits);
+                            RcTree_ReverseEncode(&p->rc, p->posEncoders + base, footerBits, (unsigned) (dist /* - base */));
+                        }
+                        else
+                        {
+                            UInt32 pos2 = (dist | 0xF) << (32 - footerBits);
+                            range = p->rc.range;
+                            // RangeEnc_EncodeDirectBits(&p->rc, posReduced >> kNumAlignBits, footerBits - kNumAlignBits);
+                            /*
+                            do
+                            {
+                              range >>= 1;
+                              p->rc.low += range & (0 - ((dist >> --footerBits) & 1));
+                              RC_NORM(&p->rc)
+                            }
+                            while (footerBits > kNumAlignBits);
+                             */
+                            do
+                            {
+                                range >>= 1;
+                                p->rc.low += range & (0 - (pos2 >> 31));
+                                pos2 += pos2;
+                                RC_NORM(&p->rc)
+                            }
+                            while (pos2 != 0xF0000000);
+
+
+                            // RcTree_ReverseEncode(&p->rc, p->posAlignEncoder, kNumAlignBits, posReduced & kAlignMask);
+
+                            {
+                                unsigned m = 1;
+                                unsigned bit;
+                                bit = dist & 1;
+                                dist >>= 1;
+                                RC_BIT(&p->rc, p->posAlignEncoder + m, bit);
+                                m = (m << 1) + bit;
+                                bit = dist & 1;
+                                dist >>= 1;
+                                RC_BIT(&p->rc, p->posAlignEncoder + m, bit);
+                                m = (m << 1) + bit;
+                                bit = dist & 1;
+                                dist >>= 1;
+                                RC_BIT(&p->rc, p->posAlignEncoder + m, bit);
+                                m = (m << 1) + bit;
+                                bit = dist & 1;
+                                RC_BIT(&p->rc, p->posAlignEncoder + m, bit);
+                                p->rc.range = range;
+                                // p->alignPriceCount++;
+                            }
+                        }
+                    }
+                }
+            }
+
+            nowPos32 += (UInt32) len;
+            p->additionalOffset -= len;
+
+            if (p->additionalOffset == 0)
+            {
+                UInt32 processed;
+
+                if (!p->fastMode)
+                {
+                    /*
+                    if (p->alignPriceCount >= 16) // kAlignTableSize
+                      FillAlignPrices(p);
+                    if (p->matchPriceCount >= 128)
+                      FillDistancesPrices(p);
+                    if (p->lenEnc.counter <= 0)
+                      LenPriceEnc_UpdateTables(&p->lenEnc, 1 << p->pb, &p->lenProbs, p->ProbPrices);
+                     */
+                    if (p->matchPriceCount >= 64)
+                    {
+                        FillAlignPrices(p);
+                        // { int y; for (y = 0; y < 100; y++) {
+                        FillDistancesPrices(p);
+                        // }}
+                        LenPriceEnc_UpdateTables(&p->lenEnc, 1 << p->pb, &p->lenProbs, p->ProbPrices);
+                    }
+                    if (p->repLenEncCounter <= 0)
+                    {
+                        p->repLenEncCounter = REP_LEN_COUNT;
+                        LenPriceEnc_UpdateTables(&p->repLenEnc, 1 << p->pb, &p->repLenProbs, p->ProbPrices);
+                    }
+                }
+
+                if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) == 0)
+                    break;
+                processed = nowPos32 - startPos32;
+
+                if (maxPackSize)
+                {
+                    if (processed + kNumOpts + 300 >= maxUnpackSize
+                            || RangeEnc_GetProcessed_sizet(&p->rc) + kPackReserve >= maxPackSize)
+                        break;
+                }
+                else if (processed >= (1 << 17))
+                {
+                    p->nowPos64 += nowPos32 - startPos32;
+                    return CheckErrors(p);
+                }
+            }
+        }
+
+    p->nowPos64 += nowPos32 - startPos32;
+    return Flush(p, nowPos32);
+}
+
+
+
+#define kBigHashDicLimit ((UInt32)1 << 24)
+
+static SRes LzmaEnc_Alloc(CLzmaEnc *p, UInt32 keepWindowSize, ISzAllocPtr alloc, ISzAllocPtr allocBig)
+{
+    UInt32 beforeSize = kNumOpts;
+    if (!RangeEnc_Alloc(&p->rc, alloc))
+        return SZ_ERROR_MEM;
+
+#ifndef _7ZIP_ST
+    p->mtMode = (p->multiThread && !p->fastMode && (p->matchFinderBase.btMode != 0));
+#endif
+
+    {
+        unsigned lclp = p->lc + p->lp;
+        if (!p->litProbs || !p->saveState.litProbs || p->lclp != lclp)
+        {
+            LzmaEnc_FreeLits(p, alloc);
+            p->litProbs = (CLzmaProb *) ISzAlloc_Alloc(alloc, ((UInt32) 0x300 << lclp) * sizeof (CLzmaProb));
+            p->saveState.litProbs = (CLzmaProb *) ISzAlloc_Alloc(alloc, ((UInt32) 0x300 << lclp) * sizeof (CLzmaProb));
+            if (!p->litProbs || !p->saveState.litProbs)
+            {
+                LzmaEnc_FreeLits(p, alloc);
+                return SZ_ERROR_MEM;
+            }
+            p->lclp = lclp;
+        }
+    }
+
+    p->matchFinderBase.bigHash = (Byte) (p->dictSize > kBigHashDicLimit ? 1 : 0);
+
+    if (beforeSize + p->dictSize < keepWindowSize)
+        beforeSize = keepWindowSize - p->dictSize;
+
+#ifndef _7ZIP_ST
+    if (p->mtMode)
+    {
+        RINOK(MatchFinderMt_Create(&p->matchFinderMt, p->dictSize, beforeSize, p->numFastBytes,
+                                   LZMA_MATCH_LEN_MAX
+                                   + 1 /* 18.04 */
+                                   , allocBig));
+        p->matchFinderObj = &p->matchFinderMt;
+        p->matchFinderBase.bigHash = (Byte) (
+                (p->dictSize > kBigHashDicLimit && p->matchFinderBase.hashMask >= 0xFFFFFF) ? 1 : 0);
+        MatchFinderMt_CreateVTable(&p->matchFinderMt, &p->matchFinder);
+    }
+    else
+#endif
+    {
+        if (!MatchFinder_Create(&p->matchFinderBase, p->dictSize, beforeSize, p->numFastBytes, LZMA_MATCH_LEN_MAX, allocBig))
+            return SZ_ERROR_MEM;
+        p->matchFinderObj = &p->matchFinderBase;
+        MatchFinder_CreateVTable(&p->matchFinderBase, &p->matchFinder);
+    }
+
+    return SZ_OK;
+}
+
+void LzmaEnc_Init(CLzmaEnc *p)
+{
+    unsigned i;
+    p->state = 0;
+    p->reps[0] =
+            p->reps[1] =
+            p->reps[2] =
+            p->reps[3] = 1;
+
+    RangeEnc_Init(&p->rc);
+
+    for (i = 0; i < (1 << kNumAlignBits); i++)
+        p->posAlignEncoder[i] = kProbInitValue;
+
+    for (i = 0; i < kNumStates; i++)
+    {
+        unsigned j;
+        for (j = 0; j < LZMA_NUM_PB_STATES_MAX; j++)
+        {
+            p->isMatch[i][j] = kProbInitValue;
+            p->isRep0Long[i][j] = kProbInitValue;
+        }
+        p->isRep[i] = kProbInitValue;
+        p->isRepG0[i] = kProbInitValue;
+        p->isRepG1[i] = kProbInitValue;
+        p->isRepG2[i] = kProbInitValue;
+    }
+
+    {
+        for (i = 0; i < kNumLenToPosStates; i++)
+        {
+            CLzmaProb *probs = p->posSlotEncoder[i];
+            unsigned j;
+            for (j = 0; j < (1 << kNumPosSlotBits); j++)
+                probs[j] = kProbInitValue;
+        }
+    }
+    {
+        for (i = 0; i < kNumFullDistances; i++)
+            p->posEncoders[i] = kProbInitValue;
+    }
+
+    {
+        UInt32 num = (UInt32) 0x300 << (p->lp + p->lc);
+        UInt32 k;
+        CLzmaProb *probs = p->litProbs;
+        for (k = 0; k < num; k++)
+            probs[k] = kProbInitValue;
+    }
+
+
+    LenEnc_Init(&p->lenProbs);
+    LenEnc_Init(&p->repLenProbs);
+
+    p->optEnd = 0;
+    p->optCur = 0;
+
+    {
+        for (i = 0; i < kNumOpts; i++)
+            p->opt[i].price = kInfinityPrice;
+    }
+
+    p->additionalOffset = 0;
+
+    p->pbMask = (1 << p->pb) - 1;
+    p->lpMask = ((UInt32) 0x100 << p->lp) - ((unsigned) 0x100 >> p->lc);
+}
+
+void LzmaEnc_InitPrices(CLzmaEnc *p)
+{
+    if (!p->fastMode)
+    {
+        FillDistancesPrices(p);
+        FillAlignPrices(p);
+    }
+
+    p->lenEnc.tableSize =
+            p->repLenEnc.tableSize =
+            p->numFastBytes + 1 - LZMA_MATCH_LEN_MIN;
+
+    p->repLenEncCounter = REP_LEN_COUNT;
+
+    LenPriceEnc_UpdateTables(&p->lenEnc, 1 << p->pb, &p->lenProbs, p->ProbPrices);
+    LenPriceEnc_UpdateTables(&p->repLenEnc, 1 << p->pb, &p->repLenProbs, p->ProbPrices);
+}
+
+static SRes LzmaEnc_AllocAndInit(CLzmaEnc *p, UInt32 keepWindowSize, ISzAllocPtr alloc, ISzAllocPtr allocBig)
+{
+    unsigned i;
+    for (i = kEndPosModelIndex / 2; i < kDicLogSizeMax; i++)
+        if (p->dictSize <= ((UInt32) 1 << i))
+            break;
+    p->distTableSize = i * 2;
+
+    p->finished = False;
+    p->result = SZ_OK;
+    RINOK(LzmaEnc_Alloc(p, keepWindowSize, alloc, allocBig));
+    LzmaEnc_Init(p);
+    LzmaEnc_InitPrices(p);
+    p->nowPos64 = 0;
+    return SZ_OK;
+}
+
+static SRes LzmaEnc_Prepare(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *inStream,
+                            ISzAllocPtr alloc, ISzAllocPtr allocBig)
+{
+    CLzmaEnc *p = (CLzmaEnc *) pp;
+    p->matchFinderBase.stream = inStream;
+    p->needInit = 1;
+    p->rc.outStream = outStream;
+    return LzmaEnc_AllocAndInit(p, 0, alloc, allocBig);
+}
+
+SRes LzmaEnc_PrepareForLzma2(CLzmaEncHandle pp,
+                             ISeqInStream *inStream, UInt32 keepWindowSize,
+                             ISzAllocPtr alloc, ISzAllocPtr allocBig)
+{
+    CLzmaEnc *p = (CLzmaEnc *) pp;
+    p->matchFinderBase.stream = inStream;
+    p->needInit = 1;
+    return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig);
+}
+
+static void LzmaEnc_SetInputBuf(CLzmaEnc *p, const Byte *src, SizeT srcLen)
+{
+    p->matchFinderBase.directInput = 1;
+    p->matchFinderBase.bufferBase = (Byte *) src;
+    p->matchFinderBase.directInputRem = srcLen;
+}
+
+SRes LzmaEnc_MemPrepare(CLzmaEncHandle pp, const Byte *src, SizeT srcLen,
+                        UInt32 keepWindowSize, ISzAllocPtr alloc, ISzAllocPtr allocBig)
+{
+    CLzmaEnc *p = (CLzmaEnc *) pp;
+    LzmaEnc_SetInputBuf(p, src, srcLen);
+    p->needInit = 1;
+
+    LzmaEnc_SetDataSize(pp, srcLen);
+    return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig);
+}
+
+void LzmaEnc_Finish(CLzmaEncHandle pp)
+{
+#ifndef _7ZIP_ST
+    CLzmaEnc *p = (CLzmaEnc *) pp;
+    if (p->mtMode)
+        MatchFinderMt_ReleaseStream(&p->matchFinderMt);
+#else
+    UNUSED_VAR(pp);
+#endif
+}
+
+typedef struct
+{
+    ISeqOutStream vt;
+    Byte *data;
+    SizeT rem;
+    BoolInt overflow;
+} CLzmaEnc_SeqOutStreamBuf;
+
+static size_t SeqOutStreamBuf_Write(const ISeqOutStream *pp, const void *data, size_t size)
+{
+    // CLzmaEnc_SeqOutStreamBuf *p = CONTAINER_FROM_VTBL(pp, CLzmaEnc_SeqOutStreamBuf, vt);
+    // if (p->rem < size)
+    // {
+    //     size = p->rem;
+    //     p->overflow = True;
+    // }
+    // memcpy(p->data, data, size);
+    // p->rem -= size;
+    // p->data += size;
+    // return size;
+}
+
+UInt32 LzmaEnc_GetNumAvailableBytes(CLzmaEncHandle pp)
+{
+    const CLzmaEnc *p = (CLzmaEnc *) pp;
+    return p->matchFinder.GetNumAvailableBytes(p->matchFinderObj);
+}
+
+const Byte *LzmaEnc_GetCurBuf(CLzmaEncHandle pp)
+{
+    const CLzmaEnc *p = (CLzmaEnc *) pp;
+    return p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset;
+}
+
+SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, BoolInt reInit,
+                             Byte *dest, size_t *destLen, UInt32 desiredPackSize, UInt32 *unpackSize)
+{
+    CLzmaEnc *p = (CLzmaEnc *) pp;
+    UInt64 nowPos64;
+    SRes res;
+    CLzmaEnc_SeqOutStreamBuf outStream;
+
+    outStream.vt.Write = SeqOutStreamBuf_Write;
+    outStream.data = dest;
+    outStream.rem = *destLen;
+    outStream.overflow = False;
+
+    p->writeEndMark = False;
+    p->finished = False;
+    p->result = SZ_OK;
+
+    if (reInit)
+        LzmaEnc_Init(p);
+    LzmaEnc_InitPrices(p);
+
+    nowPos64 = p->nowPos64;
+    RangeEnc_Init(&p->rc);
+    p->rc.outStream = &outStream.vt;
+
+    if (desiredPackSize == 0)
+        return SZ_ERROR_OUTPUT_EOF;
+
+    res = LzmaEnc_CodeOneBlock(p, desiredPackSize, *unpackSize);
+
+    *unpackSize = (UInt32) (p->nowPos64 - nowPos64);
+    *destLen -= outStream.rem;
+    if (outStream.overflow)
+        return SZ_ERROR_OUTPUT_EOF;
+
+    return res;
+}
+
+static SRes LzmaEnc_Encode2(CLzmaEnc *p, ICompressProgress *progress)
+{
+    SRes res = SZ_OK;
+
+#ifndef _7ZIP_ST
+    Byte allocaDummy[0x300];
+    allocaDummy[0] = 0;
+    allocaDummy[1] = allocaDummy[0];
+#endif
+
+    for (;;)
+    {
+        res = LzmaEnc_CodeOneBlock(p, 0, 0);
+        if (res != SZ_OK || p->finished)
+            break;
+        if (progress)
+        {
+            res = ICompressProgress_Progress(progress, p->nowPos64, RangeEnc_GetProcessed(&p->rc));
+            if (res != SZ_OK)
+            {
+                res = SZ_ERROR_PROGRESS;
+                break;
+            }
+        }
+    }
+
+    LzmaEnc_Finish(p);
+
+    /*
+    if (res == SZ_OK && !Inline_MatchFinder_IsFinishedOK(&p->matchFinderBase))
+      res = SZ_ERROR_FAIL;
+    }
+     */
+
+    return res;
+}
+
+SRes LzmaEnc_Encode(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress,
+                    ISzAllocPtr alloc, ISzAllocPtr allocBig)
+{
+    RINOK(LzmaEnc_Prepare(pp, outStream, inStream, alloc, allocBig));
+    return LzmaEnc_Encode2((CLzmaEnc *) pp, progress);
+}
+
+SRes LzmaEnc_WriteProperties(CLzmaEncHandle pp, Byte *props, SizeT *size)
+{
+    CLzmaEnc *p = (CLzmaEnc *) pp;
+    unsigned i;
+    UInt32 dictSize = p->dictSize;
+    if (*size < LZMA_PROPS_SIZE)
+        return SZ_ERROR_PARAM;
+    *size = LZMA_PROPS_SIZE;
+    props[0] = (Byte) ((p->pb * 5 + p->lp) * 9 + p->lc);
+
+    if (dictSize >= ((UInt32) 1 << 22))
+    {
+        UInt32 kDictMask = ((UInt32) 1 << 20) - 1;
+        if (dictSize < (UInt32) 0xFFFFFFFF - kDictMask)
+            dictSize = (dictSize + kDictMask) & ~kDictMask;
+    }
+    else for (i = 11; i <= 30; i++)
+        {
+            if (dictSize <= ((UInt32) 2 << i))
+            {
+                dictSize = (2 << i);
+                break;
+            }
+            if (dictSize <= ((UInt32) 3 << i))
+            {
+                dictSize = (3 << i);
+                break;
+            }
+        }
+
+    for (i = 0; i < 4; i++)
+        props[1 + i] = (Byte) (dictSize >> (8 * i));
+    return SZ_OK;
+}
+
+unsigned LzmaEnc_IsWriteEndMark(CLzmaEncHandle pp)
+{
+    return ((CLzmaEnc *) pp)->writeEndMark;
+}
+
+SRes LzmaEnc_MemEncode(CLzmaEncHandle pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
+                       int writeEndMark, ICompressProgress *progress, ISzAllocPtr alloc, ISzAllocPtr allocBig)
+{
+    SRes res;
+    CLzmaEnc *p = (CLzmaEnc *) pp;
+
+    CLzmaEnc_SeqOutStreamBuf outStream;
+
+    outStream.vt.Write = SeqOutStreamBuf_Write;
+    outStream.data = dest;
+    outStream.rem = *destLen;
+    outStream.overflow = False;
+
+    p->writeEndMark = writeEndMark;
+    p->rc.outStream = &outStream.vt;
+
+    res = LzmaEnc_MemPrepare(pp, src, srcLen, 0, alloc, allocBig);
+
+    if (res == SZ_OK)
+    {
+        res = LzmaEnc_Encode2(p, progress);
+        if (res == SZ_OK && p->nowPos64 != srcLen)
+            res = SZ_ERROR_FAIL;
+    }
+
+    *destLen -= outStream.rem;
+    if (outStream.overflow)
+        return SZ_ERROR_OUTPUT_EOF;
+    return res;
+}
+
+SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
+                const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark,
+                ICompressProgress *progress, ISzAllocPtr alloc, ISzAllocPtr allocBig)
+{
+    CLzmaEnc *p = (CLzmaEnc *) LzmaEnc_Create(alloc);
+    SRes res;
+    if (!p)
+        return SZ_ERROR_MEM;
+
+    res = LzmaEnc_SetProps(p, props);
+    if (res == SZ_OK)
+    {
+        res = LzmaEnc_WriteProperties(p, propsEncoded, propsSize);
+        if (res == SZ_OK)
+            res = LzmaEnc_MemEncode(p, dest, destLen, src, srcLen,
+                                    writeEndMark, progress, alloc, allocBig);
+    }
+
+    LzmaEnc_Destroy(p, alloc, allocBig);
+    return res;
+}

+ 76 - 0
src/master/user/lzma/LzmaEnc.h

@@ -0,0 +1,76 @@
+/*  LzmaEnc.h -- LZMA Encoder
+2017-07-27 : Igor Pavlov : Public domain */
+
+#ifndef __LZMA_ENC_H
+#define __LZMA_ENC_H
+
+#include "7zTypes.h"
+
+EXTERN_C_BEGIN
+
+#define LZMA_PROPS_SIZE 5
+
+typedef struct _CLzmaEncProps
+{
+  int level;       /* 0 <= level <= 9 */
+  UInt32 dictSize; /* (1 << 12) <= dictSize <= (1 << 27) for 32-bit version
+                      (1 << 12) <= dictSize <= (3 << 29) for 64-bit version
+                      default = (1 << 24) */
+  int lc;          /* 0 <= lc <= 8, default = 3 */
+  int lp;          /* 0 <= lp <= 4, default = 0 */
+  int pb;          /* 0 <= pb <= 4, default = 2 */
+  int algo;        /* 0 - fast, 1 - normal, default = 1 */
+  int fb;          /* 5 <= fb <= 273, default = 32 */
+  int btMode;      /* 0 - hashChain Mode, 1 - binTree mode - normal, default = 1 */
+  int numHashBytes; /* 2, 3 or 4, default = 4 */
+  UInt32 mc;       /* 1 <= mc <= (1 << 30), default = 32 */
+  unsigned writeEndMark;  /* 0 - do not write EOPM, 1 - write EOPM, default = 0 */
+  int numThreads;  /* 1 or 2, default = 2 */
+
+  UInt64 reduceSize; /* estimated size of data that will be compressed. default = (UInt64)(Int64)-1.
+                        Encoder uses this value to reduce dictionary size */
+} CLzmaEncProps;
+
+void LzmaEncProps_Init(CLzmaEncProps *p);
+void LzmaEncProps_Normalize(CLzmaEncProps *p);
+UInt32 LzmaEncProps_GetDictSize(const CLzmaEncProps *props2);
+
+
+/* ---------- CLzmaEncHandle Interface ---------- */
+
+/* LzmaEnc* functions can return the following exit codes:
+SRes:
+  SZ_OK           - OK
+  SZ_ERROR_MEM    - Memory allocation error
+  SZ_ERROR_PARAM  - Incorrect paramater in props
+  SZ_ERROR_WRITE  - ISeqOutStream write callback error
+  SZ_ERROR_OUTPUT_EOF - output buffer overflow - version with (Byte *) output
+  SZ_ERROR_PROGRESS - some break from progress callback
+  SZ_ERROR_THREAD - error in multithreading functions (only for Mt version)
+*/
+
+typedef void * CLzmaEncHandle;
+
+CLzmaEncHandle LzmaEnc_Create(ISzAllocPtr alloc);
+void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAllocPtr alloc, ISzAllocPtr allocBig);
+
+SRes LzmaEnc_SetProps(CLzmaEncHandle p, const CLzmaEncProps *props);
+void LzmaEnc_SetDataSize(CLzmaEncHandle p, UInt64 expectedDataSiize);
+SRes LzmaEnc_WriteProperties(CLzmaEncHandle p, Byte *properties, SizeT *size);
+unsigned LzmaEnc_IsWriteEndMark(CLzmaEncHandle p);
+
+SRes LzmaEnc_Encode(CLzmaEncHandle p, ISeqOutStream *outStream, ISeqInStream *inStream,
+    ICompressProgress *progress, ISzAllocPtr alloc, ISzAllocPtr allocBig);
+SRes LzmaEnc_MemEncode(CLzmaEncHandle p, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
+    int writeEndMark, ICompressProgress *progress, ISzAllocPtr alloc, ISzAllocPtr allocBig);
+
+
+/* ---------- One Call Interface ---------- */
+
+SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
+    const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark,
+    ICompressProgress *progress, ISzAllocPtr alloc, ISzAllocPtr allocBig);
+
+EXTERN_C_END
+
+#endif

+ 11 - 0
src/master/user/lzma/Precomp.h

@@ -0,0 +1,11 @@
+/* Precomp.h -- StdAfx
+2013-11-12 : Igor Pavlov : Public domain */
+
+#ifndef __7Z_PRECOMP_H
+#define __7Z_PRECOMP_H
+
+#define _7ZIP_ST
+#include "Compiler.h"
+/* #include "7zTypes.h" */
+
+#endif

+ 138 - 0
src/master/user/lzma/lzma_decompress.c

@@ -0,0 +1,138 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include "LzmaDec.h"
+#include "LzmaEnc.h"
+// #include "7zFile.h"
+#include "vFile.h"
+#include "mylib.h"
+
+//#define LZMA_RAM_USE_DEBUG
+
+#ifdef LZMA_RAM_USE_DEBUG
+static int ram_used_size = 0;
+static int ram_used_max = 0;
+#endif
+
+void *lzma_alloc(ISzAllocPtr p, size_t size)
+{
+    void *mp;
+    
+    if(size == 0)
+    {
+        return NULL;
+    }
+    
+    mp = malloc(size);
+
+#ifdef LZMA_RAM_USE_DEBUG
+    ram_used_size += _msize(mp);
+    if (ram_used_max < ram_used_size)ram_used_max = ram_used_size;
+    printk("ram used: now / max = %d / %d\n", ram_used_size, ram_used_max);
+#endif
+    
+    return mp;
+}
+
+void lzma_free(ISzAllocPtr p, void *address)
+{
+    if(address != NULL)
+    {
+#ifdef LZMA_RAM_USE_DEBUG
+        ram_used_size -= _msize(address);
+        printk("ram used: now / max = %d / %d\n", ram_used_size, ram_used_max);
+#endif
+        free(address);
+    }
+}
+
+ISzAlloc allocator = {lzma_alloc, lzma_free};
+static CLzmaDec *lz_state = NULL; 
+
+static int lzma_decompress_init(vFile* pf)
+{
+    if(lz_state != NULL) return 0;
+    
+    extern ISzAlloc allocator;
+    // uint32_t temp;
+    UInt64 unpack_size;
+    uint8_t header[LZMA_PROPS_SIZE + 8];;
+    size_t headerSize = sizeof(header);
+
+    vfread(pf, header, headerSize);
+    for(int i = 0; i < 8; i++)
+    {
+        // printf("%02x\n",header[LZMA_PROPS_SIZE + i]);
+        // unpack_size += (UInt64)(header[LZMA_PROPS_SIZE + i] << (i * 8));
+        unpack_size = (unpack_size<<(8)) | header[LZMA_PROPS_SIZE + 7-i];
+    }
+    // temp = unpack_size;
+    printf("unpack_size:%0llx\n",unpack_size);
+    
+    //分配解码内存
+    lz_state = (CLzmaDec *)lzma_alloc(NULL, sizeof(CLzmaDec));
+
+    if(lz_state != NULL)
+    {
+        LzmaDec_Construct(lz_state);
+        LzmaDec_Allocate(lz_state, header, LZMA_PROPS_SIZE, &allocator);
+        LzmaDec_Init(lz_state);
+        
+        return 0;
+    }
+    
+    return -1;
+}
+
+int lzma_decompress_read(vFile* pf, uint8_t *buffer, int size)
+{
+    /* Start to decompress file  */
+    uint32_t position, file_size;
+    size_t dcmprs_size = 0;
+    uint8_t *inBuf;
+    SizeT inProcessed;
+    SizeT outProcessed = size;
+    ELzmaFinishMode finishMode = LZMA_FINISH_ANY;
+    ELzmaStatus status;
+    SRes res;
+    
+    lzma_decompress_init(pf);
+    
+    //获取当前文件读指针
+    inBuf = vfgetpos(pf, &position);
+    //检查文件还剩下多少字节
+    file_size = vfgetlen(pf);
+    if((position + size) > file_size)
+    {
+        inProcessed = file_size - position;
+    }
+    else
+    {
+        inProcessed = size;
+    }
+    
+    //解压数据
+    if(inProcessed >= 0)
+    {
+        res = LzmaDec_DecodeToBuf(lz_state, buffer, &outProcessed, inBuf, &inProcessed, finishMode, &status);
+        dcmprs_size = outProcessed;
+
+        //重新设置文件读指针
+        position += inProcessed;
+        vfsetpos(pf, position);
+    }
+
+    return dcmprs_size;
+}
+
+void lzma_decompress_finish(void)
+{
+    LzmaDec_Free(lz_state, &allocator);
+    
+    if(lz_state != NULL)
+    {
+        lzma_free(NULL, lz_state);
+        lz_state = NULL;
+    }
+}

+ 18 - 0
src/master/user/lzma/lzma_decompress.h

@@ -0,0 +1,18 @@
+#ifndef __LZMA_SAMPLE_H__
+#define __LZMA_SAMPLE_H__
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+#include <stdint.h>
+#include "vFile.h"
+
+int lzma_decompress_read(vFile* pf, uint8_t *buffer, int size);
+void lzma_decompress_finish(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 145 - 0
src/myflash.c

@@ -0,0 +1,145 @@
+
+#include "myflash.h"
+// #include "includes.h"
+
+//flash擦除
+void Flash_RangeErase(uint32_t FlashAddress, uint32_t Size)
+{
+    FLASH_Unlock();
+    FLASH_Erase(FlashAddress, Size);
+    FLASH_Lock();
+}
+
+//flash写指定长度数据
+void Flash_BufferWrite(uint32_t address, uint32_t *p_buffer, uint32_t len)
+{
+	uint32_t EndAddr = 0;
+
+	if(address%4||len%4) {
+		return ;
+	}
+    
+    FLASH_Unlock();
+    FLASH_FastProgram(address, (uint32_t)p_buffer, len);
+
+    // EndAddr = address + len;
+    // FLASH_EnableProgram();
+    // while (address < EndAddr) {
+	// 	//FLASH_ProgramWord(address, *p_buffer);
+    //     *(volatile uint32_t *)address = *p_buffer;
+	// 	p_buffer++;
+	// 	address += 4;
+	// }
+    // FLASH_DisableProgram();
+    FLASH_Lock();
+}
+
+//flash读指定长度的数据
+void Flash_BufferRead(uint32_t address, uint32_t *buffer, uint32_t len)
+{
+    uint32_t EndAddr = 0;
+	uint32_t *p_buffer = (uint32_t *)buffer;
+    if(address%4||len%4) {
+		return ;
+	}
+    EndAddr = address + len;
+    FLASH_Unlock();
+    while (address < EndAddr) {
+		*p_buffer++ = RD_REG(address);
+		address += 4;
+	}
+    FLASH_Lock();
+}
+
+//flash读指定长度的数据
+void Flash_BufferRead_u8(uint32_t address, uint8_t *buffer, uint32_t len)
+{
+    uint32_t EndAddr = 0;
+	// uint32_t *p_buffer = (uint32_t *)buffer;
+    uint32_t data,i=0;
+    if(address%4||len%4) {
+		return ;
+	}
+    EndAddr = address + len;
+    FLASH_Unlock();
+    while (address < EndAddr) {
+		data = RD_REG(address);
+        buffer[i] = data&0xff;
+        buffer[i+1] = (data>>8)&0xff;
+        buffer[i+2] = (data>>16)&0xff;
+        buffer[i+3] = (data>>24)&0xff;
+        i+=4;
+		address += 4;
+	}
+    FLASH_Lock();
+}
+
+//读取flash中有效数据的长度
+uint32_t Flash_DatalenRead(uint32_t address,uint32_t len)
+{
+    uint32_t BeginAddr = 0;
+	uint32_t addrlen = 0;
+	uint32_t data;
+	if(address%4||len%4) {
+		return addrlen;
+	}
+    BeginAddr = address + len - 4;
+    FLASH_Unlock();
+    while(address < BeginAddr)
+	{
+		data = RD_REG(BeginAddr);
+		if(data != 0xFFFFFFFF)
+			break;
+		BeginAddr -= 4;
+	}
+    FLASH_Lock();
+
+    if(address <= BeginAddr)
+	{
+		addrlen = (BeginAddr+4) - address;
+	}
+	return addrlen;
+}
+
+/*
+#define FLASH_TEST_ADDR 0x80010000
+#define FLASH_TEST_LEN  2048 //0x800
+//flash测试
+void flash_test(void)
+{
+    static uint32_t flash_buf[FLASH_TEST_LEN/4],flash_len;
+    static uint32_t flash_read_buf[FLASH_TEST_LEN/4];
+    uint32_t i,num=0;
+    uint32_t crc;
+
+    // num = Flash_DatalenRead(FLASH_TEST_ADDR,FLASH_TEST_LEN);
+
+    Flash_BufferRead(FLASH_TEST_ADDR,flash_buf,FLASH_TEST_LEN);
+    data_dump("flash read",(uint8_t *)flash_buf,FLASH_TEST_LEN);
+    for(i = 0; i < FLASH_TEST_LEN/4; i++)
+    {
+        flash_buf[i] = 0x12345678+i;
+    }
+    data_dump("flash write",(uint8_t *)flash_buf,FLASH_TEST_LEN);
+    Flash_RangeErase(FLASH_TEST_ADDR,FLASH_TEST_LEN);
+    Flash_BufferWrite(FLASH_TEST_ADDR,flash_buf,FLASH_TEST_LEN);
+
+    //计算crc32
+    SYS_EnableAHBClock(AHB_MASK_CRC0);
+    CRC_Reset(CRC0);
+    crc = crc_block_data_calculate((uint32_t *)FLASH_TEST_ADDR,FLASH_TEST_LEN/4);
+    printf("crc = %08x\n",crc);
+
+    // memset(flash_read_buf,0,FLASH_TEST_LEN);
+    // Flash_BufferRead(FLASH_TEST_ADDR,flash_read_buf,FLASH_TEST_LEN);
+    // data_dump("flash read",(uint8_t *)flash_read_buf,FLASH_TEST_LEN);
+
+    // for(i = 0; i < FLASH_TEST_LEN/4-1; i++)
+    // {
+    //     if(flash_buf[i] != flash_read_buf[i])
+    //         num++;
+    // }
+    // printf("error num = %u\n",num);
+
+}
+*/

+ 19 - 0
src/myflash.h

@@ -0,0 +1,19 @@
+/*
+ * @Description: 
+ * @Version: 2.0
+ * @Author: Seven
+ * @Date: 2023-08-24 15:02:40
+ * @LastEditors: Seven
+ * @LastEditTime: 2023-11-15 15:35:32
+ */
+#ifndef __MYFLASH_H__
+#define __MYFLASH_H__
+#include "board.h"
+
+void Flash_RangeErase(uint32_t FlashAddress, uint32_t Size);
+void Flash_BufferWrite(uint32_t address, uint32_t *p_buffer, uint32_t len);
+void Flash_BufferRead(uint32_t address, uint32_t *buffer, uint32_t len);
+void Flash_BufferRead_u8(uint32_t address, uint8_t *buffer, uint32_t len);
+uint32_t Flash_DatalenRead(uint32_t address,uint32_t len);
+void flash_test(void);
+#endif // !

+ 545 - 0
src/ota.c

@@ -0,0 +1,545 @@
+/*
+ * @Description:
+ * @Version: 2.0
+ * @Author: Seven
+ * @Date: 2023-11-09 14:38:52
+ * @LastEditors: Seven
+ * @LastEditTime: 2023-11-17 17:17:12
+ */
+#include "ota.h"
+#include "update.h"
+#include "myflash.h"
+#include "delay.h"
+#include "type.h"
+#include "uart.h"
+#include "bsp.h"
+#include "lzma_decompress.h"
+#include "crc32.h"
+#include "bspatch.h"
+#include "ota_flash.h"
+
+ota_info_t ota_info;
+DFOTA_pkg_header_t dfota_pkg_header;
+DFOTA_blk_header_t dfota_blk_header;
+
+
+
+
+// uint8_t test_buf[128] = {0};
+// uint32_t test_buf1[128] = {0};
+
+// void my_copy(uint32_t *da,uint32_t len)
+// {
+//     uint8_t i;
+//     for(i = 0; i < len/4; i++)
+//     {
+//         da[i] = test_buf1[i];
+//     }
+// }
+
+//升级过程
+uint8_t ota_process(void)
+{
+    uint8_t temp;
+    uint32_t i;
+    uint8_t blk_ret;
+    uint32_t get_crc3;
+    U32_U8 header_buff[24] = {0};
+    uint32_t blk_addr = 0;
+    uint32_t blk_len = 0;
+    uint8_t blk_res;
+
+    // image_header_t ih;
+    uint32_t uimage_addr;
+    uint32_t size, dcrc, crc, ocrc;
+    uint32_t app_addr, image_len, unpk_len;
+    uint8_t *image_p, *patch_p;
+    uint8_t *buff;
+    vFile* vfp;
+    uint32_t old_size;
+    uint32_t new_file;
+
+    uint8_t bk_buf[4];
+    uint32_t bk_len=0,len1=0;
+
+    // DFOTA_pkg_header_t *pkg_header = (DFOTA_pkg_header_t *)header_buff;
+
+    if(app_check(OTA_UPDATE_APP3_FLASH_START_ADDR,OTA_UPDATE_APP3_FLASH_SIZE,&get_crc3))//校验错误
+    {
+        printf("app3校验错误\n");
+        return OTA_RET_APP3_CRC_ERR;
+    }
+
+
+    memset(&dfota_pkg_header,0,PKG_HEADER_LEN);
+    Flash_BufferRead(OTA_UPDATE_APP3_FLASH_START_ADDR,(uint32_t *)header_buff,PKG_HEADER_LEN);//读升级包开头24字节
+    memcpy(&dfota_pkg_header,header_buff,PKG_HEADER_LEN);
+
+
+    if(strstr(dfota_pkg_header.pkg_magic,"DFOTA"))//合成包
+    {
+        printf("合成包\n");
+        blk_addr = 24;//头 24字节
+        while((dfota_pkg_header.pkg_size-8) >= blk_addr)
+        {
+            blk_ret = blk_check(OTA_UPDATE_APP3_FLASH_START_ADDR+blk_addr,&blk_len);
+            printf("blk_ret:%d\n",blk_ret);
+            if(blk_ret == 0)//是当前块
+            {
+                blk_res = 1;
+                break;
+            }
+            if((blk_len > 256*1024) || (blk_len <= BLK_HEADER_LEN))//块错误,退出
+            {
+                blk_res = 0;
+                break;
+            }
+            blk_addr += blk_len;
+        }
+        if(blk_res)//找到对应的块
+        {
+            if((dfota_blk_header.z_flag==0) && (dfota_blk_header.d_flag==0))//未压缩,未差分
+            {
+                printf("未压缩未差分\n");
+                //直接拷贝
+                erase_app(ota_info.update_enum);//擦除APP1
+                ota_info.erase_app1 = 1;
+                app_addr = (OTA_UPDATE_APP3_FLASH_START_ADDR+blk_addr+BLK_HEADER_LEN);//升级包的首地址
+                size = blk_len - BLK_HEADER_LEN - dfota_blk_header.pad_size - 4;//升级文件大小
+                copy_app_specify_length(ota_info.update_enum,app_addr,size);
+
+                if(!update_pkg_crc_check(ota_info.update_enum,size,dfota_blk_header.new_crc32))//升级后的crc校验错误
+                {
+                    printf("升级后的crc校验错误\n");
+                    return OTA_RET_NEWCRC_ERR;
+                }
+                printf("升级完成\n");
+                return OTA_RET_SUCCESS;
+            }
+            else if((dfota_blk_header.z_flag==1) && (dfota_blk_header.d_flag==0))//LZMA压缩,未差分
+            {
+                printf("压缩未差分\n");
+                //分配内存
+                buff = (uint8_t *)malloc(FLASH_PAGE_SIZE*8+4);
+                if(NULL == buff)
+                    return OTA_RET_NEWSIZE_ERR;
+
+                erase_app(ota_info.update_enum);//擦除APP1
+                ota_info.erase_app1 = 1;
+                //解压uzimage的数据段
+                // image_p = flash_read_fp(flash_bak, IAP_BAK_ADDR + UIMAGE_HEADER_LEN);
+                image_p = (uint8_t *)(OTA_UPDATE_APP3_FLASH_START_ADDR+blk_addr+BLK_HEADER_LEN);//压缩包的首地址
+                size = blk_len - BLK_HEADER_LEN - dfota_blk_header.pad_size - 4;//压缩文件大小
+                vfp = vfopen(image_p, size);
+                app_addr = 0;
+                image_len = 0;
+                bk_len = 0;
+                while(1)
+                {
+                    unpk_len = lzma_decompress_read(vfp, buff+bk_len, FLASH_PAGE_SIZE*8);
+                    if(bk_len)
+                    {
+                        memcpy(buff,bk_buf,bk_len);
+                    }
+                    len1 = unpk_len+bk_len;
+                    if(len1%4)//len长度不是4的整数倍
+                    {
+                        bk_len = len1%4;
+                        memcpy(bk_buf,buff+len1-bk_len,bk_len);//剩余的字节备份
+                    }
+                    else
+                    {
+                        bk_len = 0;
+                    }
+                    len1 -= bk_len;
+
+                    printf("i=%u,unpk_len:%u,write_len:%u\n",i++,unpk_len,len1);
+                    if(unpk_len == 0)break;
+
+                    if((app_addr > 256*1024) || (app_addr > dfota_blk_header.new_size)) break;
+                    if((app_addr < dfota_blk_header.new_size) && ((app_addr+len1) > dfota_blk_header.new_size))
+                    {
+                        len1 = dfota_blk_header.new_size-app_addr;
+                    }
+                    flash_write_without(ota_info.update_enum, app_addr, buff, len1);
+                    app_addr += len1;
+                    image_len += unpk_len;
+                }
+                free(buff);
+                printf("new_size:<0x%08x,%u>,image_len:<0x%08x,%u>\n",dfota_blk_header.new_size,dfota_blk_header.new_size,app_addr,app_addr);
+                if(dfota_blk_header.new_size != app_addr)//解压后的字节数错误
+                {
+                    printf("解压后的字节数错误\n");
+                    return OTA_RET_NEWSIZE_ERR;
+                }
+                if(!update_pkg_crc_check(ota_info.update_enum,app_addr,dfota_blk_header.new_crc32))//解压后的crc校验错误
+                {
+                    printf("解压后的crc校验错误\n");
+                    return OTA_RET_NEWCRC_ERR;
+                }
+                printf("升级完成\n");
+                return OTA_RET_SUCCESS;
+            }
+            else if((dfota_blk_header.z_flag==1) && (dfota_blk_header.d_flag==1))//LZMA压缩,diff差分
+            {
+                printf("压缩并差分\n");
+                if(ota_info.old_size != dfota_blk_header.old_size)
+                {
+                    printf("旧固件长度错误\n");
+                    return OTA_RET_OLDSIZE_ERR;
+                }
+                printf("old_crc_get:0x%08x,old_crc_read:0x%08x\n",ota_info.old_crc32,dfota_blk_header.old_crc32);
+                if(ota_info.old_crc32 != dfota_blk_header.old_crc32)
+                {
+                    printf("旧固件crc校验错误\n");
+                    return OTA_RET_OLDCRC_ERR;
+                }
+
+                erase_app(ota_info.update_enum);//擦除APP1
+                ota_info.erase_app1 = 1;
+                //将差分包和APP合并,数据保存到备份区
+                // image_p = flash_read_fp(flash_bak, IAP_BAK_ADDR + UIMAGE_HEADER_LEN);
+                flash_addr_get(ota_info.update_enum,0,0,&new_file);//new_file 差分后写入的flash地址
+                size = blk_len - BLK_HEADER_LEN - dfota_blk_header.pad_size - 4;//压缩文件大小
+                patch_p = (uint8_t *)(OTA_UPDATE_APP3_FLASH_START_ADDR+blk_addr+BLK_HEADER_LEN);//压缩包的首地址
+                image_p = (uint8_t *)(OTA_UPDATE_APP2_FLASH_START_ADDR);//旧固件的首地址
+                old_size = ota_info.old_size;//旧固件的大小
+                image_len = iap_patch(image_p, old_size, patch_p, size, new_file);
+
+                printf("new_size:<0x%08x,%u>,image_len:<0x%08x,%u>\n",dfota_blk_header.new_size,dfota_blk_header.new_size,image_len,image_len);
+                if(dfota_blk_header.new_size != image_len)//解压后的字节数错误
+                {
+                    printf("解压后的字节数错误\n");
+                    return OTA_RET_NEWSIZE_ERR;
+                }
+                if(!update_pkg_crc_check(ota_info.update_enum,image_len,dfota_blk_header.new_crc32))//解压后的crc校验错误
+                {
+                    printf("解压后的crc校验错误\n");
+                    return OTA_RET_NEWCRC_ERR;
+                }
+                printf("升级完成\n");
+                return OTA_RET_SUCCESS;
+            }
+        }
+        else
+        {
+            return OTA_RET_NO_BLK_ERR;
+        }
+
+    }
+    else//原始bin文件
+    {
+        printf("原始包\n");
+        //直接拷贝
+        erase_app(ota_info.update_enum);//擦除APP1
+        ota_info.erase_app1 = 1;
+        temp = firmware_tail_check(UPDATE_ENUM_APP3,&size);
+        printf("size=%d\n",size);
+        if(temp)//包含尾部20字节
+        {
+            size -= 20;
+        }
+        // app_addr = (OTA_UPDATE_APP3_FLASH_START_ADDR);//升级包的首地址
+        // size = ota_info.old_size;//升级文件大小
+        copy_app_specify_length(ota_info.update_enum,OTA_UPDATE_APP3_FLASH_START_ADDR,size);
+
+        return OTA_RET_SUCCESS;
+    }
+
+    // for(i = 0; i < 128; i++)
+    // {
+    //     test_buf[i] = rand()%0x100;
+    //     test_buf1[i] = rand()%0xffffffff;
+    //     printf("%08x ",test_buf1[i]);
+    // }
+    // printf("\n");
+    // // data_dump("u",test_buf,128);
+    // // memcpy(header_buff,test_buf,24);
+    // my_copy((uint32_t *)header_buff,32);
+    // memcpy(&dfota_pkg_header,header_buff,24);
+    // data_dump("magic",pkg_header->pkg_magic,16);
+    // printf("pkg_time=0x%08x\n",pkg_header->pkg_time);
+    // data_dump("magic1",dfota_pkg_header.pkg_magic,16);
+    // printf("pkg_time1=0x%08x\n",dfota_pkg_header.pkg_time);
+}
+
+
+//块校验
+uint8_t blk_check(uint32_t addr, uint32_t *len)
+{
+    uint32_t get_blk;
+    U32_U8 buff[44] = {0};
+    // DFOTA_blk_header_t *blk_header = (DFOTA_blk_header_t *)buff;
+    memset(&dfota_blk_header,0,BLK_HEADER_LEN);
+    Flash_BufferRead(addr,(uint32_t *)buff,BLK_HEADER_LEN);//读块开头40字节
+    memcpy(&dfota_blk_header,buff,BLK_HEADER_LEN);
+    *len = dfota_blk_header.blk_size;
+    printf("new_ver:0x%08x,new_size:0x%08x,new_crc:0x%08x,new_ep:0x%08x\n",dfota_blk_header.new_ver,dfota_blk_header.new_size,\
+    dfota_blk_header.new_crc32,dfota_blk_header.new_ep);
+    if(!strstr(dfota_blk_header.blk_magic,"BLOK"))//魔数,块标记错误
+    {
+        return 1;
+    }
+    if(app_check(addr,dfota_blk_header.blk_size,&get_blk))//校验错误
+    {
+        return 2;
+    }
+    if((dfota_blk_header.d_flag) && (dfota_blk_header.old_ver != ota_info.old_ver))//差分且旧版本号不一致
+    {
+        return 3;
+    }
+    return 0;
+}
+
+//判断固件中是否包含尾部20字节
+//返回值    1 包含;0 不包含
+uint8_t firmware_tail_check(uint32_t part, uint32_t *firm_len)
+{
+    uint32_t addr,addr_len;
+    uint32_t read_len;
+
+    uint32_t crcVl,fixChar,fileVer,filelen,fileaddr;
+	uint32_t getcrc;
+    switch(part)
+    {
+        case UPDATE_ENUM_BOOT:
+            addr = OTA_UPDATE_BOOTROM_FLASH_START_ADDR;
+            addr_len = OTA_UPDATE_BOOTROM_SIZE;
+        break;
+        case UPDATE_ENUM_PT:
+            addr = OTA_UPDATE_PT_FLASH_START_ADDR;
+            addr_len = OTA_UPDATE_PT_FLASH_SIZE;
+        break;
+        case UPDATE_ENUM_APP1:
+            addr = OTA_UPDATE_APP1_FLASH_START_ADDR;
+            addr_len = OTA_UPDATE_APP1_FLASH_SIZE;
+        break;
+        case UPDATE_ENUM_APP2:
+            addr = OTA_UPDATE_APP2_FLASH_START_ADDR;
+            addr_len = OTA_UPDATE_APP2_FLASH_SIZE;
+        break;
+        case UPDATE_ENUM_APP3:
+            addr = OTA_UPDATE_APP3_FLASH_START_ADDR;
+            addr_len = OTA_UPDATE_APP3_FLASH_SIZE;
+        break;
+        default:
+            return 0;
+        break;
+    }
+
+    read_len = Flash_DatalenRead(addr,addr_len);
+    *firm_len = read_len;
+
+    crcVl = *(uint32_t*)(addr+read_len-4); //CRC校验
+    fixChar = *(uint32_t*)(addr+read_len-8); // 固定字符 WBJW
+    fileVer = *(uint32_t*)(addr+read_len-12); // 固件版本信息
+	fileaddr = *(uint32_t*)(addr+read_len-16); // 存储地址
+    filelen = *(uint32_t*)(addr+read_len-20); // 文件总长度
+
+    printf("read_crc:%x, get_crc:%x\n",crcVl,getcrc);
+    printf("read_filelen:%08x, total_bytes:%08x\n",filelen,(read_len-20));
+    printf("read_fixchar:%08x, fixchar:%08x\n",fixChar,WBJW);
+    if(WBJW != fixChar)//固定字符错误
+        return 0;
+    printf("read_filelen:%08x, total_bytes:%08x\n",filelen,(read_len-20));
+    if(read_len != (filelen+20))//长度错误
+        return 0;
+
+    //计算crc32
+    SYS_EnableAHBClock(AHB_MASK_CRC0);
+    CRC_Reset(CRC0);
+    getcrc = crc_block_data_calculate((uint32_t *)addr,(read_len -4)/4);
+    printf("read_crc:%x, get_crc:%x\n",crcVl,getcrc);
+    if(getcrc!=crcVl)  //校验错误
+        return 0;
+
+    return 1;
+}
+
+//备份
+uint8_t app_backup(void)
+{
+    uint8_t ret = 0;
+    erase_app(UPDATE_ENUM_APP2);
+    printf("firm:%d\n",ota_info.firmware_type);
+    switch(ota_info.firmware_type)
+    {
+        case FIRMTYPE_PT:
+            copy_app(UPDATE_ENUM_PT, UPDATE_ENUM_APP2);
+            device_mcu_info.app2_ver = device_mcu_info.pt_ver;
+            device_mcu_info.pt_ver = device_mcu_info.app3_ver;
+        break;
+        case FIRMTYPE_APP:
+            copy_app(UPDATE_ENUM_APP1, UPDATE_ENUM_APP2);
+            device_mcu_info.app2_ver = device_mcu_info.app1_ver;
+            device_mcu_info.app1_ver = device_mcu_info.app3_ver;
+        break;
+        default:
+            ret = 1;
+        break;
+    }
+    return ret;
+}
+
+//计算老版本信息
+void old_firm_info_cal(void)
+{
+    uint32_t temp;
+
+    switch(ota_info.firmware_type)
+    {
+        case FIRMTYPE_PT:
+            ota_info.old_ver = device_mcu_info.pt_ver;
+            ota_info.old_size = Flash_DatalenRead(OTA_UPDATE_PT_FLASH_START_ADDR,OTA_UPDATE_PT_FLASH_SIZE);
+            SYS_EnableAHBClock(AHB_MASK_CRC0);
+            CRC_Reset(CRC0);
+            ota_info.old_crc32 = crc_block_data_calculate((uint32_t *)OTA_UPDATE_PT_FLASH_START_ADDR,ota_info.old_size/4);
+            ota_info.update_enum = UPDATE_ENUM_PT;
+            ota_info.tail_flag = firmware_tail_check(UPDATE_ENUM_PT,&temp);
+        break;
+        case FIRMTYPE_APP:
+            ota_info.old_ver = device_mcu_info.app1_ver;
+            ota_info.old_size = Flash_DatalenRead(OTA_UPDATE_APP1_FLASH_START_ADDR,OTA_UPDATE_APP1_FLASH_SIZE);
+            SYS_EnableAHBClock(AHB_MASK_CRC0);
+            CRC_Reset(CRC0);
+            ota_info.old_crc32 = crc_block_data_calculate((uint32_t *)OTA_UPDATE_APP1_FLASH_START_ADDR,ota_info.old_size/4);
+            ota_info.update_enum = UPDATE_ENUM_APP1;
+            ota_info.tail_flag = firmware_tail_check(UPDATE_ENUM_APP1,&temp);
+            printf("old_size:<0x%08x,%u>,old_crc:0x%08x\n",ota_info.old_size,ota_info.old_size,ota_info.old_crc32);
+        break;
+        default:
+
+        break;
+    }
+}
+
+//回退
+void ota_backoff(uint8_t update_type)
+{
+    uint16_t write_data_dr2;
+    uint8_t part;
+    if(update_type == 2)//产测
+    {
+        part = UPDATE_ENUM_PT;
+    }
+    else if(update_type == 3)//app
+    {
+        part = UPDATE_ENUM_APP1;
+    }
+    else
+    {
+        return;
+    }
+    erase_app(part);
+    copy_app(UPDATE_ENUM_APP2,part);
+    write_data_dr2 = set_flag_not(BACKOFF_OVER);
+    RTC_WriteBackupRegister(BKP_UPDATE_FLAG,write_data_dr2);
+
+    if(update_type == 2)//产测
+    {
+        device_mcu_info.pt_ver = device_mcu_info.app2_ver;
+        updata_flag = 1;
+    }
+    else if(update_type == 3)//app
+    {
+        device_mcu_info.app1_ver = device_mcu_info.app2_ver;
+        updata_flag = 1;
+    }
+    else if(update_type == 4)//fpga
+    {
+        device_mcu_info.fpga_ver = device_mcu_info.app2_ver;
+        updata_flag = 1;
+    }
+}
+
+//IAP主程序
+void myiap_task(void)
+{
+    uint8_t p_ret;
+    uint16_t write_data_dr2;
+    uint16_t data_dr1,data_dr2,data_dr3;
+    data_dr1 = RTC_ReadBackupRegister(BKP_UPDATE_FLAG);//升级标志
+    printf("BKP_UPDATE_FLAG=%04x\n",data_dr1);
+    if(flag_not_cmp(data_dr1))
+    {
+        data_dr2 = RTC_ReadBackupRegister(BKP_UPDATE_FIRM_TYPE);//升级固件类型
+        printf("BKP_UPDATE_FIRM=%04x\n",data_dr2);
+
+        if((data_dr1&0x00ff) == UPDATA_FLAG)//升级
+		{
+            if(!flag_not_cmp(data_dr2))//升级固件类型错误
+            {
+                printf("升级固件类型错误\n");
+                write_data_dr2 = set_flag_not(UPDATE_ERR);
+                RTC_WriteBackupRegister(BKP_UPDATE_FLAG,write_data_dr2);
+
+                write_data_dr2 = set_flag_not(OTA_RET_FIRMWARE_ERR);
+                RTC_WriteBackupRegister(BKP_UPDATE_STATE,write_data_dr2);
+                return;
+            }
+            memset(&ota_info,0,sizeof(ota_info_t));
+            ota_info.firmware_type = data_dr2&0x00ff;
+            old_firm_info_cal();//计算旧固件信息
+            if(app_backup()==0)//备份成功
+            {
+                printf("updata begin\n");
+			    p_ret = ota_process();
+                if(p_ret == OTA_RET_SUCCESS)//升级成功
+                {
+                    updata_flag = 1;
+                    write_data_dr2 = set_flag_not(BACKOFF_FLAG);
+                    RTC_WriteBackupRegister(BKP_UPDATE_FLAG,write_data_dr2);
+                }
+                else//升级失败
+                {
+                    if(ota_info.erase_app1)//app1已经擦除,需要回退
+                    {
+                        ota_info.erase_app1 = 0;
+                        ota_backoff(ota_info.firmware_type);//回退
+                    }
+
+                    write_data_dr2 = set_flag_not(UPDATE_ERR);
+                    RTC_WriteBackupRegister(BKP_UPDATE_FLAG,write_data_dr2);
+
+                    write_data_dr2 = set_flag_not(p_ret);
+                    RTC_WriteBackupRegister(BKP_UPDATE_STATE,write_data_dr2);
+                }
+            }
+            else
+            {
+                printf("升级固件类型错误1\n");
+                write_data_dr2 = set_flag_not(UPDATE_ERR);
+                RTC_WriteBackupRegister(BKP_UPDATE_FLAG,write_data_dr2);
+
+                write_data_dr2 = set_flag_not(OTA_RET_FIRMWARE_ERR);
+                RTC_WriteBackupRegister(BKP_UPDATE_STATE,write_data_dr2);
+            }
+		}
+        else if((data_dr1&0x00ff) == BACKOFF_FLAG)//回退
+        {
+            if(!flag_not_cmp(data_dr2))//升级固件类型错误
+            {
+                printf("升级固件类型错误\n");
+                write_data_dr2 = set_flag_not(UPDATE_ERR);
+                RTC_WriteBackupRegister(BKP_UPDATE_FLAG,write_data_dr2);
+
+                write_data_dr2 = set_flag_not(OTA_RET_FIRMWARE_ERR);
+                RTC_WriteBackupRegister(BKP_UPDATE_STATE,write_data_dr2);
+                return;
+            }
+            ota_info.firmware_type = data_dr2&0x00ff;
+
+            printf("back off begin\n");
+            ota_backoff(ota_info.firmware_type);
+        }
+        else if((data_dr1&0x00ff) == BACKOFF_OVER)//回退失败
+		{
+			RTC_WriteBackupRegister(BKP_UPDATE_FLAG,0x0000);
+		}
+        else
+        {
+            RTC_WriteBackupRegister(BKP_UPDATE_FLAG,0x0000);
+        }
+    }
+}
+

+ 166 - 0
src/ota.h

@@ -0,0 +1,166 @@
+#ifndef __OTA_H__
+#define __OTA_H__
+#include <stdint.h>
+#include <stdbool.h>
+
+#define WBJW    0x57424A57
+
+#define MAX_BIN_SIZE        (256*1024)      //单个bin文件最大值;
+#define MAX_OLDFILES_NUM    8	            //旧bin文件的个数的最大值;
+#define BLOCK_MAX           8	            //块数量的最大值;
+#define NEW_EP              (0X80000000)	//入口地址;
+
+#define MAX_PATH 8
+
+
+/**************************** 以下为结构体定义*****************************/
+
+//升级固件类型
+#define FIRMTYPE_BT     1
+#define FIRMTYPE_PT     2
+#define FIRMTYPE_APP    3
+
+#define DF_PKG  1   //差分包
+#define FS_PKG  2   //原始包
+//升级信息
+typedef struct _ota_info_t
+{
+    uint8_t firmware_type;              //固件类型
+    uint32_t old_ver;                   //旧版本号
+    uint32_t old_size;                  //旧字节数
+    uint32_t old_crc32;                 //旧crc32
+    uint8_t pkg_type;                   //升级包类型
+    uint8_t update_enum;                //固件标记
+    uint8_t tail_flag;                  //是否包含尾部20字节
+    uint8_t erase_app1;                 //是否已擦除app1
+}ota_info_t;
+extern ota_info_t ota_info;
+
+
+//升级过程结果
+enum {
+    OTA_RET_SUCCESS     = 0,            //执行成功
+    OTA_RET_APP3_CRC_ERR   = 0x31,       //APP3校验错误
+    OTA_RET_NO_BLK_ERR,         //没找到对应的块
+    OTA_RET_NEWSIZE_ERR,        //升级后的字节数错误
+    OTA_RET_NEWCRC_ERR,         //升级后的crc错误
+    OTA_RET_OLDSIZE_ERR,        //旧固件的字节数错误
+    OTA_RET_OLDCRC_ERR,         //旧固件的crc错误
+    OTA_RET_FIRMWARE_ERR,       //固件类型错误
+};
+
+
+typedef struct{
+    bool ok;
+    char* path;
+    char drive[MAX_PATH];
+    char dir[MAX_PATH];
+    char filename[MAX_PATH];
+    char ext[MAX_PATH];
+    uint8_t* addr;
+    uint32_t size;
+    uint32_t app_ver;
+    uint16_t dev_type;
+    uint32_t crc32;
+}bin_file_t;
+
+
+#pragma pack(1)                     // 1字节对齐
+// 下载包,结构体
+typedef struct{
+    uint8_t* pkg_addr;              // 下载包的首地址;
+
+    uint32_t pkg_size;              // 下载包的大小,完整的;从数据包里解析出来的原始字段值
+    uint32_t pkg_crc32;             // 下载包的crc32;从数据包里解析出来的原始字段值
+    uint32_t calc_pkg_size;             // 下载包的大小,完整的;经过计算的值 calc_size == pkg_size
+    uint32_t calc_pkg_crc32;            // 下载包的crc32;经过计算的值 calc_crc32 = crc32(pkg_addr,calc_size - 4)
+}DFOTA_pkg_t;
+
+// 下载包,头,结构体,
+// header_size = sizeof(DFOTA_pkg_header_t)
+typedef struct{
+    uint8_t  pkg_magic[16];         // ="DFOTA_PK_V002"; 魔数,差分升级标记,整个下载包的起始标记
+    uint32_t pkg_time;              // 打包的时间戳;
+    uint32_t pkg_size;              // 从数据包里解析出来的原始字段值
+}DFOTA_pkg_header_t;
+
+// 块,结构体
+// DFOTA_blk_t block[BLOCK_MAX]     // 数组定义
+typedef struct{
+    uint8_t* blk_addr;              // 第n个块的首地址;
+
+    uint32_t blk_size;              // 第n个块的大小,完整的;从数据包里解析出来的原始字段值
+    uint32_t blk_crc32;             // 第n个块的crc32;从数据包里解析出来的原始字段值
+
+    uint32_t calc_blk_size;             // 第n个块的大小,完整的;经过计算的值 calc_size == blk_size
+    uint32_t calc_blk_crc32;            // 第n个块的crc32;经过计算的值 calc_crc32 = crc32(blk_addr,calc_size - 4)
+
+    uint8_t* payload_addr;          // 载荷的首地址;
+    uint32_t payload_size;          // 载荷的大小,完整的
+
+}DFOTA_blk_t;
+
+//块,头,结构体,header_size = sizeof(DFOTA_pkg_header_t)
+typedef struct{
+    uint8_t  blk_magic[4];          // ="BLOK"//魔数,块标记
+    uint32_t blk_size;              // 此字段之后crc32之前的字节数
+    uint8_t  d_flag;                // 差分算法标记
+    uint8_t  z_flag;                // 压缩算法标记
+    uint16_t reserve;               // 预留
+    uint32_t old_ver;               // 旧固件[old.bin]的版本号
+    uint32_t old_size;              // 旧固件[old.bin]的字节数
+    uint32_t old_crc32;             // 旧固件[old.bin]的crc32
+    uint32_t new_ver;               // 新固件[new.bin]的版本号
+    uint32_t new_size;              // 新固件[new.bin]的字节数
+    uint32_t new_crc32;             // 新固件[new.bin]的crc32
+    uint32_t new_ep;                // 新固件[new.bin]的入口地址
+    uint32_t pad_size;              // block尾部填充字节数
+}DFOTA_blk_header_t;
+
+// 载荷,结构体
+typedef struct{
+    uint8_t* diff_header_addr;      // 差分头首地址
+    uint8_t* compr_header_addr;     // 压缩头首地址
+
+    uint8_t* data_addr;             // data首地址
+    uint32_t data_size;             // data的大小;
+}DFOTA_payload_t;
+
+// 差分,头,结构体,header_size = sizeof(DFOTA_bsdiff_header_t)
+typedef struct{
+    uint8_t  diff_magic[16];        // ="ENDSLEY/BSDIFF43"
+    uint32_t new_size;              // new file size in Byte(s)(new.bin的字节数)
+}DFOTA_bsdiff_header_t;
+
+// 压缩,头,结构体,header_size = sizeof(DFOTA_lzma_header_t)
+typedef struct{
+    uint8_t  props;                 // Special LZMA properties (lc,lp, pb in encoded form)
+    uint32_t dic;                   // Dictionary size (little endian)
+    uint64_t raw_size;              // 没压缩时的字节数diff_raw.bin的字节数)
+}DFOTA_lzma_header_t;
+
+// DFOTA设备相关参数结构体定义
+typedef struct{
+    uint32_t current_ver;           // 当前版本
+    uint32_t current_size;          // 当前版本
+    uint32_t current_crc32;         // 当前版本
+
+    uint32_t blk_sum;               // 实际解析到的块的个数
+    uint32_t blk_match_index;       // 索引到的匹配的块下标
+
+    //.....
+}DFOTA_dev_t;
+
+
+#pragma pack()                      // 取消1字节对齐,恢复为默认4字节对齐
+
+#define PKG_HEADER_LEN  sizeof(DFOTA_pkg_header_t)  //24字节
+#define BLK_HEADER_LEN  sizeof(DFOTA_blk_header_t)  //44字节
+
+
+uint8_t firmware_tail_check(uint32_t part, uint32_t *firm_len);
+uint8_t ota_process(void);
+uint8_t blk_check(uint32_t addr, uint32_t *len);
+void myiap_task(void);
+
+#endif // !

+ 41 - 0
src/uart.c

@@ -0,0 +1,41 @@
+/*
+ * @Description: 
+ * @Version: 2.0
+ * @Author: Seven
+ * @Date: 2023-08-31 08:58:03
+ * @LastEditors: Seven
+ * @LastEditTime: 2023-08-31 09:00:06
+ */
+#include "uart.h"
+
+void uart0_init(void)
+{
+    GPIO_AF_ENABLE(GPIO_AF_PIN(UART, 0, UARTRXD));
+    GPIO_AF_ENABLE(GPIO_AF_PIN(UART, 0, UARTTXD));
+
+    MSG_UART = UARTx(0);
+    SYS_EnableAPBClock(APB_MASK_UARTx(0));
+    UART_Init(UARTx(0), 115200, UART_LCR_DATABITS_8, UART_LCR_STOPBITS_1, UART_LCR_PARITY_NONE, UART_LCR_FIFO_16);
+}
+
+
+void data_dump(const char *name, uint8_t *data, uint16_t length)
+{
+	int index = 0;
+
+	printf("%s Data Info: \r\n    ", name);
+
+	for(index = 0;index < length;index++) {
+		if((index%4 == 0)&&index) {
+			if((index%16 == 0)&&index) {
+				printf("\r\n    ");
+			} else {
+				printf(" ");
+			}
+		}
+		printf("%02X ", *(data + index));
+	}
+	printf("\r\n");
+}
+
+

+ 7 - 0
src/uart.h

@@ -0,0 +1,7 @@
+#ifndef UART_H__
+#define UART_H__
+#include "board.h"
+
+void uart0_init(void);
+void data_dump(const char *name, uint8_t *data, uint16_t length);
+#endif // !

+ 370 - 0
src/update.c

@@ -0,0 +1,370 @@
+/*
+ * @Description: 
+ * @Version: 2.0
+ * @Author: Seven
+ * @Date: 2023-08-29 11:44:39
+ * @LastEditors: Seven
+ * @LastEditTime: 2023-11-16 15:02:37
+ */
+#include "update.h"
+#include "myflash.h"
+#include "delay.h"
+#include "type.h"
+#include "bsp.h"
+#include "mylib.h"
+
+extern void IWDG_feed(void);
+
+//擦除app
+int erase_app(uint8_t app_num)
+{
+    uint32_t FlashAddress = 0;
+    uint32_t Size = OTA_UPDATE_APP_FLASH_SIZE;
+    switch (app_num)
+    {
+        case UPDATE_ENUM_APP1:
+            FlashAddress = OTA_UPDATE_APP1_FLASH_START_ADDR;
+        break;
+        case UPDATE_ENUM_APP2:
+            FlashAddress = OTA_UPDATE_APP2_FLASH_START_ADDR;
+        break;
+        case UPDATE_ENUM_APP3:
+            FlashAddress = OTA_UPDATE_APP3_FLASH_START_ADDR;
+        break;
+        case UPDATE_ENUM_PT:
+            FlashAddress = OTA_UPDATE_PT_FLASH_START_ADDR;
+            Size = OTA_UPDATE_PT_FLASH_SIZE;
+        break;
+        case UPDATE_ENUM_FPGA:
+            FlashAddress = OTA_UPDATE_FPGA_FLASH_START_ADDR;
+            Size = OTA_UPDATE_FPGA_FLASH_SIZE;
+        break;
+    
+        default:
+            return -1;
+        break;
+    }
+    Flash_RangeErase(FlashAddress, Size);
+    return 0;
+}
+
+
+//复制
+int copy_app(uint8_t from, uint8_t to)
+{
+    uint32_t FromFlashAddress = 0;
+    uint32_t Size;
+    uint32_t Size_p = OTA_UPDATE_APP_FLASH_SIZE;
+    uint32_t ToFlashAddress = 0;
+    uint32_t buffer[256];
+    int size;
+    switch(from)
+    {
+        case UPDATE_ENUM_APP1:
+            FromFlashAddress = OTA_UPDATE_APP1_FLASH_START_ADDR;
+        break;
+        case UPDATE_ENUM_APP2:
+            FromFlashAddress = OTA_UPDATE_APP2_FLASH_START_ADDR;
+        break;
+        case UPDATE_ENUM_APP3:
+            FromFlashAddress = OTA_UPDATE_APP3_FLASH_START_ADDR;
+        break;
+        case UPDATE_ENUM_PT:
+            FromFlashAddress = OTA_UPDATE_PT_FLASH_START_ADDR;
+			Size_p = OTA_UPDATE_PT_FLASH_SIZE;
+        break;
+        case UPDATE_ENUM_FPGA:
+            FromFlashAddress = OTA_UPDATE_FPGA_FLASH_START_ADDR;
+            Size_p = OTA_UPDATE_FPGA_FLASH_SIZE;
+        break;
+        default:
+        return -1;
+    }
+
+    switch (to)
+    {
+        case UPDATE_ENUM_APP1:
+            ToFlashAddress = OTA_UPDATE_APP1_FLASH_START_ADDR;
+        break;
+        case UPDATE_ENUM_APP2:
+            ToFlashAddress = OTA_UPDATE_APP2_FLASH_START_ADDR;
+        break;
+        case UPDATE_ENUM_APP3:
+            ToFlashAddress = OTA_UPDATE_APP3_FLASH_START_ADDR;
+        break;
+        case UPDATE_ENUM_PT:
+            ToFlashAddress = OTA_UPDATE_PT_FLASH_START_ADDR;
+			// Size_p = OTA_UPDATE_PT_FLASH_SIZE;
+        break;
+        case UPDATE_ENUM_FPGA:
+            ToFlashAddress = OTA_UPDATE_FPGA_FLASH_START_ADDR;
+			// Size_p = OTA_UPDATE_FPGA_FLASH_SIZE;
+        break;
+        default:
+        return -1;
+    }
+    Size = Flash_DatalenRead(FromFlashAddress,Size_p);
+    size = Size;
+    // printf("size = %u\n",size);
+
+    while(size > 0)
+    {
+        Flash_BufferRead(FromFlashAddress, buffer, 1024);
+		Flash_BufferWrite(ToFlashAddress, buffer, 1024);
+		FromFlashAddress += 1024;
+		ToFlashAddress += 1024;		
+		size -= 1024;
+    }
+    return 0;
+}
+
+//拷贝app指定长度
+int copy_app_specify_length(UPDATE_ENUM to, uint32_t addr, uint32_t len)
+{
+    uint32_t from_addr;
+    uint32_t phy_addr;
+    uint32_t buffer[256];
+    int size; 
+    uint32_t addr_len;
+    if(len%4) return(FALSE);
+    if(FALSE == flash_addr_get(to, 0, len, &phy_addr))return(FALSE);
+    size = len;
+    from_addr = addr;
+    while(size > 0)
+    {
+        len = (size > 1024) ? 1024 : size;
+        Flash_BufferRead(from_addr, buffer, len);
+		Flash_BufferWrite(phy_addr, buffer, len);
+		phy_addr += len;
+		from_addr += len;		
+		size -= len;
+    }
+    return TRUE;
+}
+
+/**
+ * @brief 获取FLASH数据地址
+ * @details 将FALSH分区地址转换为物理地址
+ *
+ * @param  part 分区号
+ * @param  addr 分区内数据相对地址
+ * @param  len 要操作的数据长度
+ * @param  *phy_addr 返回的物理地址
+ * @return 操作的数据是否在分区内
+ *   @retval TRUE 合法的操作
+ *   @retval FALSE 非法的操作
+ */
+int flash_addr_get(UPDATE_ENUM part, uint32_t addr, uint32_t len, uint32_t *phy_addr)
+{
+    switch(part)                               //检查存储类型
+    {
+    case UPDATE_ENUM_BOOT:
+        if((addr + len) > OTA_UPDATE_BOOTROM_SIZE) return(FALSE);
+        *phy_addr = OTA_UPDATE_BOOTROM_FLASH_START_ADDR + addr;
+        break;
+
+    case UPDATE_ENUM_PT:
+        if((addr + len) > OTA_UPDATE_PT_FLASH_SIZE)return(FALSE);
+        *phy_addr = OTA_UPDATE_PT_FLASH_START_ADDR + addr;
+        break;
+    
+    case UPDATE_ENUM_APP1:
+        if((addr + len) > OTA_UPDATE_APP1_FLASH_SIZE)return(FALSE);
+        *phy_addr = OTA_UPDATE_APP1_FLASH_START_ADDR + addr;
+        break;    
+
+    case UPDATE_ENUM_APP2:
+        if((addr + len) > OTA_UPDATE_APP2_FLASH_SIZE)return(FALSE);
+        *phy_addr = OTA_UPDATE_APP2_FLASH_START_ADDR + addr;
+        break;
+    
+    case UPDATE_ENUM_APP3:
+        if((addr + len) > OTA_UPDATE_APP3_FLASH_SIZE)return(FALSE);
+        *phy_addr = OTA_UPDATE_APP3_FLASH_START_ADDR + addr;
+        break;
+
+    default:
+        return(FALSE);
+    }
+    return(TRUE);
+}
+
+/**
+ * @brief 分区数据写入
+ * @details 当前分区数据写入,不支持非对齐写入
+ *
+ * @param  part 分区号
+ * @param  addr 相对地址
+ * @param  p 数据指针
+ * @param  len 数据长度
+ * @return 操作结果
+ *   @retval 无 
+ */
+int flash_write_without(UPDATE_ENUM app_num, uint32_t addr, const void *p, uint32_t len)
+{
+    uint32_t phy_addr;
+    U32_U8 dat;
+    // uint8_t *datp = (uint8_t*)p;
+    uint32_t *datp = (uint32_t *)p;
+    int i;    
+    
+    if(FALSE == flash_addr_get(app_num, addr, len, &phy_addr))
+    {
+        printf("write addr err\n");
+        return(FALSE);
+    }
+    
+    IWDG_feed();
+    // FLASH_Unlock();
+    if((phy_addr % 4) != 0)
+    {
+        printf("write len err\n");
+        return(FALSE);
+    }
+
+    Flash_BufferWrite(phy_addr,(uint32_t *)datp,len);
+    
+    // while(len)
+    // {
+    //     dat.d32 = 0xFFFFFFFF;
+    //     for(i = 0; i < 4; i++)
+    //     {
+    //         if(len > 0)
+    //         {
+    //             dat.d8[i] = *(datp++);
+    //             len--;
+    //         }
+    //     }
+    //     // FLASH_ProgramWord(phy_addr, dat.d32); //按字写入
+    //     // FLASH_FastProgram(phy_addr, dat.d32, 4);//按字写入
+    //     // Flash_BufferWrite(phy_addr,(uint32_t *)&dat.d32,4);
+    //     phy_addr += 4;
+    //     //每写入1K数据,喂一次狗
+    //     if(0 == (phy_addr & 0x3FF))
+    //     {
+    //         IWDG_feed();
+    //     }
+    // }
+    // FLASH_Lock();
+    
+    return(TRUE);
+}
+
+
+
+/**
+ * @brief 分区数据写入
+ * @details 当前分区数据写入,支持非对齐写入,写之前不需要擦除
+ *
+ * @param  part 分区号
+ * @param  addr 相对地址
+ * @param  p 数据指针
+ * @param  len 数据长度
+ * @return 操作结果
+ *   @retval 无 
+ */
+// int flash_write_1(UPDATE_ENUM part, uint32_t addr, const void *p, uint32_t len)
+// {
+//     uint32_t pg, pd, offset;
+//     uint32_t page_addr, phy_addr;
+//     uint8_t  *buff;
+//     uint8_t *datp = (uint8_t*)p;
+
+//     if(FALSE == flash_addr_get(part, addr, len, &phy_addr))return(FALSE);
+
+//     IWDG_feed();
+//     //申请内存
+//     buff = (uint8_t *)malloc(FLASH_SECTOR_SIZE);
+//     if(NULL == buff)
+//     {
+//         printk("FLASH:memory allocation failure...\r\n");
+//         return(FALSE);
+//     }
+
+//     FLASH_Unlock();							    //解锁FLASH编写擦除控制器
+//     pg = phy_addr / FLASH_SECTOR_SIZE;            //计算扇区号
+//     offset = phy_addr % FLASH_SECTOR_SIZE;        //计算扇区内偏移
+//     pd = FLASH_SECTOR_SIZE - offset;          	//计算当前地址所在的扇区还可以写多少字节
+//     if(len <= pd)pd = len;                 		//判断数据是否在当前页内
+//     page_addr = pg * FLASH_SECTOR_SIZE;	        //计算扇区物理地址
+//     // flash_page_read(page_addr, buff);		    //读取数据
+//     Flash_BufferRead(page_addr,buff,FLASH_SECTOR_SIZE);//读取数据
+
+//     //判断要写入的区域是否为0xFF
+//     if((FALSE == mylib_memcmp_b(buff + offset, 0xFF, pd)) || (offset % 4))
+//     {
+//         // FLASH_ErasePage(page_addr);		    //擦除一个扇区
+//     }
+//     memcpy(buff + offset, datp, pd);		    //修改数据
+//     flash_page_write(page_addr, buff);		    //写入数据
+
+//     len -= pd;                         		    //判断剩下的数据长度
+//     datp += pd;                                 //移动数据指针
+//     while(len)                            		//如果没有写完,写到下一页
+//     {
+//         pg++;                           		//扇区号指向下一扇区
+//         page_addr = pg * FLASH_PAGE_SIZE;	    //计算物理地址
+//         if(len >= FLASH_PAGE_SIZE)            	//如果剩下的数据大于扇区长度
+//         {
+//             flash_page_read(page_addr, buff);  //读取该扇区
+//             //判断要写入的区域是否为0xFF
+//             if(FALSE == mylib_memcmp_b(buff, 0xFF, FLASH_PAGE_SIZE))
+//             {
+//                 FLASH_ErasePage(page_addr);    //擦除一个扇区
+//             }
+//             flash_page_write(page_addr, datp); //写入数据
+//             len -= FLASH_PAGE_SIZE;
+//             datp += FLASH_PAGE_SIZE;
+//         }
+//         else
+//         {
+//             flash_page_read(page_addr, buff);  //读取该扇区
+//             //判断要写入的区域是否为0xFF
+//             if(FALSE == mylib_memcmp_b(buff, 0xFF, len))
+//             {
+//                 FLASH_ErasePage(page_addr);    //擦除一个扇区
+//             }
+//             memcpy(buff, datp, len);            //修改数据
+//             flash_page_write(page_addr, buff); //写入数据
+//             len = 0;
+//         }
+//     }
+//     FLASH_Lock();
+//     free(buff);
+    
+//     return(TRUE);
+// }
+
+
+
+/*
+升级包校验判断
+*/
+int update_pkg_crc_check(UPDATE_ENUM part, uint32_t len, uint32_t check_crc)
+{
+    uint32_t get_crc;
+    uint32_t phy_addr;
+    if(FALSE == flash_addr_get(part, 0, len, &phy_addr))return(FALSE);
+
+    //计算crc32
+    SYS_EnableAHBClock(AHB_MASK_CRC0);
+    CRC_Reset(CRC0);
+    get_crc = crc_block_data_calculate((uint32_t *)phy_addr,len/4);
+    printf("len:<0x%08x,%u>,read_crc:0x%08x,get_crc:0x%08x\n",len,len,check_crc,get_crc);
+
+    if(get_crc == check_crc)
+        return (TRUE);
+    else
+        return (FALSE);
+}
+
+
+//跳转
+uint32_t run_app1(void)
+{
+    uint32_t appxaddr = OTA_UPDATE_APP1_FLASH_START_ADDR;//;
+    printf("jump to 0x%08X\r\n",appxaddr);
+    delay_us(1200);
+    
+    UTIL_JumpToAddress(appxaddr);
+}

+ 58 - 0
src/update.h

@@ -0,0 +1,58 @@
+/*
+ * @Description: 
+ * @Version: 2.0
+ * @Author: Seven
+ * @Date: 2023-08-30 09:45:29
+ * @LastEditors: Seven
+ * @LastEditTime: 2023-11-16 09:50:11
+ */
+#ifndef UPDATE_H__
+#define UPDATE_H__
+#include "board.h"
+
+typedef enum UPDATE_ENUM {
+	UPDATE_ENUM_NONE,
+	UPDATE_ENUM_BOOT,
+	UPDATE_ENUM_APP1,
+	UPDATE_ENUM_APP2,
+	UPDATE_ENUM_APP3,
+    UPDATE_ENUM_PT,
+	UPDATE_ENUM_FPGA,
+	UPDATE_ENUM_MAX	
+} UPDATE_ENUM;
+
+#define OTA_UPDATE_BOOTROM_SIZE               (0x10000)
+#define OTA_UPDATE_BOOTROM_FLASH_START_ADDR   (0x80000000)                                                          //
+#define OTA_UPDATE_BOOTROM_FLASH_END_ADDR     (OTA_UPDATE_BOOTROM_FLASH_START_ADDR+OTA_UPDATE_BOOTROM_SIZE-1)
+
+#define OTA_UPDATE_PT_FLASH_SIZE              (0x10000)
+#define OTA_UPDATE_PT_FLASH_START_ADDR        (0x80010000)
+#define OTA_UPDATE_PT_FLASH_END_ADDR          (OTA_UPDATE_PT_FLASH_START_ADDR+OTA_UPDATA_PT_FLASH_SIZE-1)
+
+#define OTA_UPDATE_APP1_FLASH_SIZE            (0x40000)                                                             //
+#define OTA_UPDATE_APP1_FLASH_START_ADDR      (0x80020000)                                                          //
+#define OTA_UPDATE_APP1_FLASH_END_ADDR        (OTA_UPDATE_APP1_FLASH_START_ADDR+OTA_UPDATE_APP1_FLASH_SIZE-1)       //
+
+#define OTA_UPDATE_APP2_FLASH_SIZE            (0x40000)                                                             //
+#define OTA_UPDATE_APP2_FLASH_START_ADDR      (0x80060000)                                                          //
+#define OTA_UPDATE_APP2_FLASH_END_ADDR        (OTA_UPDATE_APP2_FLASH_START_ADDR+OTA_UPDATE_APP2_FLASH_SIZE-1)       //
+
+#define OTA_UPDATE_APP3_FLASH_SIZE            (0x40000)                                                             //
+#define OTA_UPDATE_APP3_FLASH_START_ADDR      (0x800A0000)                                                          //
+#define OTA_UPDATE_APP3_FLASH_END_ADDR        (OTA_UPDATE_APP3_FLASH_START_ADDR+OTA_UPDATE_APP3_FLASH_SIZE-1)       //
+
+#define OTA_UPDATE_FPGA_FLASH_SIZE            (0x19000)                                                             //
+#define OTA_UPDATE_FPGA_FLASH_START_ADDR      (0x800E7000)                                                          //
+#define OTA_UPDATE_FPGA_FLASH_END_ADDR        (OTA_UPDATE_FPGA_FLASH_START_ADDR+OTA_UPDATE_FPGA_FLASH_SIZE-1)       //
+
+#define OTA_UPDATE_APP_FLASH_SIZE             (0x40000)
+
+int erase_app(uint8_t app_num);
+int copy_app(uint8_t from, uint8_t to);
+int copy_app_specify_length(UPDATE_ENUM to, uint32_t addr, uint32_t len);
+uint32_t run_app1(void);
+
+int flash_addr_get(UPDATE_ENUM part, uint32_t addr, uint32_t len, uint32_t *phy_addr);
+int flash_write_without(UPDATE_ENUM app_num, uint32_t addr, const void *p, uint32_t len);
+int update_pkg_crc_check(UPDATE_ENUM part, uint32_t len, uint32_t check_crc);
+#endif // !