firestarter 3.2.4__tar.gz → 3.2.6__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {firestarter-3.2.4/firestarter.egg-info → firestarter-3.2.6}/PKG-INFO +1 -1
- {firestarter-3.2.4 → firestarter-3.2.6}/firestarter/_version.py +3 -3
- {firestarter-3.2.4 → firestarter-3.2.6}/firestarter/chip_resolver.py +10 -1
- {firestarter-3.2.4 → firestarter-3.2.6}/firestarter/cli_handlers.py +4 -2
- {firestarter-3.2.4 → firestarter-3.2.6}/firestarter/codec.py +3 -2
- {firestarter-3.2.4 → firestarter-3.2.6}/firestarter/data/chip_database.json +52 -16
- {firestarter-3.2.4 → firestarter-3.2.6}/firestarter/data/pinouts.json +10 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/firestarter/database.py +5 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/firestarter/firmware.py +20 -8
- firestarter-3.2.6/firestarter/flash4_erase_gate.py +104 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/firestarter/ic_layout.py +7 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/firestarter/jumper_table.py +10 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/firestarter/serial_comm.py +10 -1
- {firestarter-3.2.4 → firestarter-3.2.6/firestarter.egg-info}/PKG-INFO +1 -1
- {firestarter-3.2.4 → firestarter-3.2.6}/firestarter.egg-info/scm_file_list.json +1 -0
- firestarter-3.2.6/firestarter.egg-info/scm_version.json +8 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/__snapshots__/test_characterization.ambr +7 -4
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/golden/chip_database_field_inventory.json +31 -27
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/golden/wire_dict.json +35 -6
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_build_db_inclusion.py +74 -3
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_chip_resolver.py +33 -3
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_chip_test.py +1 -1
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_codec.py +2 -2
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_codec_format_message.py +2 -2
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_datasheet_overrides.py +1 -1
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_decoder.py +3 -3
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_eprom_database.py +16 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_extra_chips_supplement.py +22 -2
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_firmware_install.py +62 -29
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_flash4_erase_gate.py +98 -102
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_info_vpp_and_erase.py +6 -5
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_jumper_table.py +8 -5
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_lock_status_class_partition.py +6 -5
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_programming_vcc_census.py +25 -16
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_vpp_rail_classification.py +21 -11
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_write_blank_guard_pinning.py +4 -1
- firestarter-3.2.4/firestarter/flash4_erase_gate.py +0 -79
- firestarter-3.2.4/firestarter.egg-info/scm_version.json +0 -8
- {firestarter-3.2.4 → firestarter-3.2.6}/LICENSE +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/MANIFEST.in +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/README.md +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/firestarter/__init__.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/firestarter/address_parser.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/firestarter/avr_tool.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/firestarter/channel.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/firestarter/chip_test.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/firestarter/compare.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/firestarter/config.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/firestarter/constants.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/firestarter/diagnostic_report.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/firestarter/dip24_2816_erase_gate.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/firestarter/eprom_info.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/firestarter/eprom_operations.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/firestarter/erase_support.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/firestarter/exceptions.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/firestarter/frame_parser.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/firestarter/fw_release_gate.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/firestarter/hardware.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/firestarter/jp5_gate.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/firestarter/lock_status.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/firestarter/log_capture.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/firestarter/logging_utils.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/firestarter/main.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/firestarter/messages.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/firestarter/page_size_gate.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/firestarter/protection_readability.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/firestarter/py32_dfu.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/firestarter/sdp_capability.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/firestarter/sdp_honesty.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/firestarter/submit.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/firestarter/timestamps.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/firestarter/transport_counters.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/firestarter/utils.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/firestarter/vpp_display.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/firestarter/write_blank_guard.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/firestarter.egg-info/SOURCES.txt +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/firestarter.egg-info/dependency_links.txt +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/firestarter.egg-info/entry_points.txt +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/firestarter.egg-info/requires.txt +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/firestarter.egg-info/top_level.txt +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/pyproject.toml +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/setup.cfg +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/__init__.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/conftest.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/fake_chip.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/fixtures/part_number_delta.json +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/fixtures/report_shapes.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/fixtures/reports/at28c256-full-all-ok-sdp.json +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/fixtures/reports/attr01-status-axis-transport-fault.json +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/fixtures/reports/gh20-at28c256-fail.json +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/fixtures/reports/gh23-w27e257-fail.json +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/fixtures/reports/gh28-m27c512-fail.json +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/fixtures/reports/gh47-sst27sf512-pass.json +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/fixtures/reports/m27c512-full-all-ok.json +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/fixtures/reports/m27c512-full-blank-check-bad.json +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/fixtures/reports/m27c512-full-canonical-name.json +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/fixtures/reports/m27c512-full-comma-joined-name.json +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/fixtures/reports/m27c512-full-runs-1.json +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/fixtures/reports/prune03-synthesized-fingerprint-match.json +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/fixtures/reports/sst27sf512-full-all-ok.json +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/fixtures/reports/sst27sf512-six-step-readback-gated.json +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/fixtures/reports/sst27sf512-six-step.json +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/fixtures/reports/synthetic-arm4-empty-results.json +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/fixtures/reports/synthetic-arm4-no-ok.json +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/fixtures/reports/uv-slot-write-pass.json +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/fixtures/reports/w27e257-full-all-ok.json +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/fixtures/shape_ids.json +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/fixtures/synthetic_nonzero_chip_id.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/golden/build_db_part_specific_constants.json +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/plan_corpus.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_address_parser.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_b15_page_size_corroboration.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_blast_radius_invariance.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_boot_block_hint.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_budget_failure_render.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_bug_characterization.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_build_db_constant_census.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_build_db_interpret_timing.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_build_db_pinout_fork.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_canonical_part_number.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_characterization.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_chip_database_field_inventory.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_chip_name_resolution.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_chip_test_blank_check_order.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_chip_test_cycle.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_chip_test_sdp_leg.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_chip_test_timing.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_chip_test_uv_slot_write.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_cli_handlers.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_click_group_gate_hook.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_cobs.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_compare.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_config.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_config_band_refusal.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_connect_cost_harness.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_consistency_check.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_coverage_floor_v18.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_database_conversion.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_derive_plan_no_drop_sweep.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_derive_plan_structural_sentinel.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_dev_group_channel_gating.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_dev_test_cmd.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_dev_tools_channel_gate.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_devtest_firmware_error_propagation.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_dfu_opcode_anchors.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_diagnostic_report.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_dip24_2816_erase_gate.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_endpoint_constants.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_eprom_info.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_eprom_operations.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_erase_blank_step_nonregression.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_erase_flag_invariants.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_error_code_seam.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_even_block.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_fw_list_failure_vs_empty.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_fw_port_targeting_and_blind_install.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_fw_release_gate.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_fw_update_dead_endpoint.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_fw_update_path_gate.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_fw_version_guard.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_fwguard.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_hardware.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_hw_revision_gate.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_ic_layout.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_jp5_gate.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_lock_status_cli.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_lock_status_wire.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_log_capture.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_logging_utils.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_matrix_artifact.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_page_size_alignment_refusal.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_page_size_invariants.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_page_size_write_refusal.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_parse_devtest_issue.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_probe_spurious_setup_ack.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_protect_flags_doc_measurements.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_protection_resolution.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_protection_status_catalog.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_protection_table_citations.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_protocol_not_implemented.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_protocol_not_implemented_production_path.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_provenance.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_pulse_us_override.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_py32_channel_gating.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_py32_dfu.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_py32_flash_map_host.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_py32_pyusb_absent.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_pyusb_api_surface.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_sdp_capability.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_sdp_db_invariant.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_sdp_honesty.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_serial_characterization.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_serial_comm.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_session_lease.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_setup_refusals.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_submit.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_timestamps.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_transport_counters.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_utils.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_uv_mask.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_validate_family_cmd.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_validate_oracle.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_validated_parts_regression_surface.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_vcc_margin_rail.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_vpp_decode_table.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_wire_dict_equivalence.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_write_blank_guard.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_write_guard_port_pinning.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_write_progress.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_write_response_budget.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_write_skip_erase_0x0d.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_write_skip_sdp_unlock.py +0 -0
- {firestarter-3.2.4 → firestarter-3.2.6}/tests/test_write_verify.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: firestarter
|
|
3
|
-
Version: 3.2.
|
|
3
|
+
Version: 3.2.6
|
|
4
4
|
Summary: EPROM programmer software for the Relatively Universal ROM Programmer
|
|
5
5
|
Author-email: Henrik Olsson <henols@gmail.com>
|
|
6
6
|
Project-URL: Homepage, https://github.com/henols/firestarter_app
|
|
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
|
|
|
18
18
|
commit_id: str | None
|
|
19
19
|
__commit_id__: str | None
|
|
20
20
|
|
|
21
|
-
__version__ = version = '3.2.
|
|
22
|
-
__version_tuple__ = version_tuple = (3, 2,
|
|
21
|
+
__version__ = version = '3.2.6'
|
|
22
|
+
__version_tuple__ = version_tuple = (3, 2, 6)
|
|
23
23
|
|
|
24
|
-
__commit_id__ = commit_id = '
|
|
24
|
+
__commit_id__ = commit_id = 'g6a02a12'
|
|
@@ -9,7 +9,7 @@ Single chokepoint between CLI dispatch and the EPROM database lookup/conversion.
|
|
|
9
9
|
|
|
10
10
|
from typing import Any
|
|
11
11
|
|
|
12
|
-
from firestarter.database import EpromDatabase
|
|
12
|
+
from firestarter.database import ROM_CE, ROM_OE, EpromDatabase
|
|
13
13
|
from firestarter.exceptions import (
|
|
14
14
|
AmbiguousChipNameError,
|
|
15
15
|
ChipNotFoundError,
|
|
@@ -133,6 +133,15 @@ def resolve_chip(name: str, db: EpromDatabase | None = None) -> dict[str, Any]:
|
|
|
133
133
|
# A pin map with fewer address lines than the chip's size needs would
|
|
134
134
|
# repeat one window of the chip across the whole operation, silently.
|
|
135
135
|
bus = data.get("bus-config", {}).get("bus")
|
|
136
|
+
# The shield wires one socket pin to its CE driver and one to its OE
|
|
137
|
+
# driver. get_bus_config gives an address pin there the ROM_CE / ROM_OE
|
|
138
|
+
# sentinel, which is not a bus line the firmware can drive.
|
|
139
|
+
if bus and {ROM_CE, ROM_OE} & set(bus):
|
|
140
|
+
raise ChipNotImplementedError(
|
|
141
|
+
f"{name}: its pin map puts an address line on a socket pin that the "
|
|
142
|
+
"shield drives as CE or OE. The programmer cannot drive that "
|
|
143
|
+
"address line."
|
|
144
|
+
)
|
|
136
145
|
if bus and data["memory-size"] > 1 << len(bus):
|
|
137
146
|
raise ChipNotImplementedError(
|
|
138
147
|
f"{name}: its pin map has {len(bus)} address lines, which reach "
|
|
@@ -1443,9 +1443,11 @@ def erase(
|
|
|
1443
1443
|
|
|
1444
1444
|
eprom_data = resolve_chip(eprom, db=app.db)
|
|
1445
1445
|
|
|
1446
|
+
# The database leaves FLAG_CAN_ERASE clear for flash4, so `write` never
|
|
1447
|
+
# carries it. The erase sets it for this command only; setup_command
|
|
1448
|
+
# refuses it on firmware without the 5 V software chip erase.
|
|
1446
1449
|
if flash4_erase_gate.is_flash4(eprom_data):
|
|
1447
|
-
|
|
1448
|
-
sys.exit(0 if ignore_unsupported else 1)
|
|
1450
|
+
eprom_data = flash4_erase_gate.with_erase_flag(eprom_data)
|
|
1449
1451
|
|
|
1450
1452
|
full_record = app.db.get_eprom(eprom) or {}
|
|
1451
1453
|
if dip24_2816_erase_gate.is_affected(full_record.get("pin-map")):
|
|
@@ -74,7 +74,8 @@ def format_message(msg_id: int, params: List[Any], entry: MessageDef) -> str | N
|
|
|
74
74
|
|
|
75
75
|
P-02 MSG_OK_REV — params[0]=physical u8, params[1]=effective u8
|
|
76
76
|
effective==0xFF → "Rev{physical}" (no override)
|
|
77
|
-
effective!=0xFF → "Rev{effective},
|
|
77
|
+
effective!=0xFF → "Rev{effective}, Detected HW: Rev{physical}"
|
|
78
|
+
(the override is in effect; the second field is what the board detected)
|
|
78
79
|
|
|
79
80
|
P-03 MSG_OK_CFG — params[0]=r1 u32, params[1]=r2 u32, params[2]=override u8,
|
|
80
81
|
params[3]=bandgap_mv u16 (absent on firmware before 3.1.0b4)
|
|
@@ -104,7 +105,7 @@ def format_message(msg_id: int, params: List[Any], entry: MessageDef) -> str | N
|
|
|
104
105
|
if effective == 0xFF:
|
|
105
106
|
return phys_str
|
|
106
107
|
eff_str = _REVISION_SILKSCREEN.get(effective, f"Rev{effective}")
|
|
107
|
-
return f"{eff_str},
|
|
108
|
+
return f"{eff_str}, Detected HW: {phys_str}"
|
|
108
109
|
|
|
109
110
|
if msg_id == MSG_OK_CFG and len(params) in (3, 4):
|
|
110
111
|
r1, r2, override = params[0], params[1], params[2]
|
|
@@ -1710,7 +1710,8 @@
|
|
|
1710
1710
|
"protect_on_after": false,
|
|
1711
1711
|
"pulse_duration_us": 100
|
|
1712
1712
|
},
|
|
1713
|
-
"support_status": "
|
|
1713
|
+
"support_status": "protocol-not-implemented",
|
|
1714
|
+
"unsupported_reason": "protocol not implemented: pin map DIP28_27011 gives 14 address lines, which reach 16384 of the chip's 131072 bytes. The programmer implements no way to reach the rest."
|
|
1714
1715
|
},
|
|
1715
1716
|
{
|
|
1716
1717
|
"electrical": {
|
|
@@ -5989,7 +5990,7 @@
|
|
|
5989
5990
|
"vpp_mv": 12500
|
|
5990
5991
|
},
|
|
5991
5992
|
"part_number": "MBM27C1000P,MBM27C1000",
|
|
5992
|
-
"pinout": "
|
|
5993
|
+
"pinout": "DIP32_27C301",
|
|
5993
5994
|
"programming": {
|
|
5994
5995
|
"algorithm": 8,
|
|
5995
5996
|
"chip_id_check": true,
|
|
@@ -5999,7 +6000,8 @@
|
|
|
5999
6000
|
"protect_on_after": false,
|
|
6000
6001
|
"pulse_duration_us": 500
|
|
6001
6002
|
},
|
|
6002
|
-
"support_status": "
|
|
6003
|
+
"support_status": "adapter-required",
|
|
6004
|
+
"unsupported_reason": "adapter required: the shield drives chip pin 22 as CE and pin 24 as OE, but pin map DIP32_27C301 needs other functions on pins [2, 24]. An adapter must move those pins."
|
|
6003
6005
|
},
|
|
6004
6006
|
{
|
|
6005
6007
|
"electrical": {
|
|
@@ -6058,7 +6060,7 @@
|
|
|
6058
6060
|
"vpp_mv": 12500
|
|
6059
6061
|
},
|
|
6060
6062
|
"part_number": "MBM27C2000P,MBM27C2000",
|
|
6061
|
-
"pinout": "
|
|
6063
|
+
"pinout": "DIP32_27C301",
|
|
6062
6064
|
"programming": {
|
|
6063
6065
|
"algorithm": 8,
|
|
6064
6066
|
"chip_id_check": true,
|
|
@@ -6068,7 +6070,8 @@
|
|
|
6068
6070
|
"protect_on_after": false,
|
|
6069
6071
|
"pulse_duration_us": 100
|
|
6070
6072
|
},
|
|
6071
|
-
"support_status": "
|
|
6073
|
+
"support_status": "adapter-required",
|
|
6074
|
+
"unsupported_reason": "adapter required: the shield drives chip pin 22 as CE and pin 24 as OE, but pin map DIP32_27C301 needs other functions on pins [2, 24]. An adapter must move those pins."
|
|
6072
6075
|
},
|
|
6073
6076
|
{
|
|
6074
6077
|
"electrical": {
|
|
@@ -6464,7 +6467,7 @@
|
|
|
6464
6467
|
"vpp_mv": 12500
|
|
6465
6468
|
},
|
|
6466
6469
|
"part_number": "HN27C301AG,HN27C301AP,HN27C301AFP",
|
|
6467
|
-
"pinout": "
|
|
6470
|
+
"pinout": "DIP32_27C301",
|
|
6468
6471
|
"programming": {
|
|
6469
6472
|
"algorithm": 8,
|
|
6470
6473
|
"chip_id_check": true,
|
|
@@ -6474,7 +6477,8 @@
|
|
|
6474
6477
|
"protect_on_after": false,
|
|
6475
6478
|
"pulse_duration_us": 100
|
|
6476
6479
|
},
|
|
6477
|
-
"support_status": "
|
|
6480
|
+
"support_status": "adapter-required",
|
|
6481
|
+
"unsupported_reason": "adapter required: the shield drives chip pin 22 as CE and pin 24 as OE, but pin map DIP32_27C301 needs other functions on pins [2, 24]. An adapter must move those pins."
|
|
6478
6482
|
},
|
|
6479
6483
|
{
|
|
6480
6484
|
"electrical": {
|
|
@@ -6486,7 +6490,7 @@
|
|
|
6486
6490
|
"vpp_mv": 12500
|
|
6487
6491
|
},
|
|
6488
6492
|
"part_number": "HN27C301G",
|
|
6489
|
-
"pinout": "
|
|
6493
|
+
"pinout": "DIP32_27C301",
|
|
6490
6494
|
"programming": {
|
|
6491
6495
|
"algorithm": 8,
|
|
6492
6496
|
"chip_id_check": false,
|
|
@@ -6496,7 +6500,8 @@
|
|
|
6496
6500
|
"protect_on_after": false,
|
|
6497
6501
|
"pulse_duration_us": 100
|
|
6498
6502
|
},
|
|
6499
|
-
"support_status": "
|
|
6503
|
+
"support_status": "adapter-required",
|
|
6504
|
+
"unsupported_reason": "adapter required: the shield drives chip pin 22 as CE and pin 24 as OE, but pin map DIP32_27C301 needs other functions on pins [2, 24]. An adapter must move those pins."
|
|
6500
6505
|
},
|
|
6501
6506
|
{
|
|
6502
6507
|
"electrical": {
|
|
@@ -7407,7 +7412,8 @@
|
|
|
7407
7412
|
"protect_on_after": false,
|
|
7408
7413
|
"pulse_duration_us": 100
|
|
7409
7414
|
},
|
|
7410
|
-
"support_status": "
|
|
7415
|
+
"support_status": "protocol-not-implemented",
|
|
7416
|
+
"unsupported_reason": "protocol not implemented: pin map DIP28_27011 gives 14 address lines, which reach 16384 of the chip's 131072 bytes. The programmer implements no way to reach the rest."
|
|
7411
7417
|
},
|
|
7412
7418
|
{
|
|
7413
7419
|
"electrical": {
|
|
@@ -7429,7 +7435,8 @@
|
|
|
7429
7435
|
"protect_on_after": false,
|
|
7430
7436
|
"pulse_duration_us": 100
|
|
7431
7437
|
},
|
|
7432
|
-
"support_status": "
|
|
7438
|
+
"support_status": "protocol-not-implemented",
|
|
7439
|
+
"unsupported_reason": "protocol not implemented: pin map DIP28_27011 gives 14 address lines, which reach 16384 of the chip's 131072 bytes. The programmer implements no way to reach the rest."
|
|
7433
7440
|
},
|
|
7434
7441
|
{
|
|
7435
7442
|
"electrical": {
|
|
@@ -11966,7 +11973,7 @@
|
|
|
11966
11973
|
"vpp_mv": 13000
|
|
11967
11974
|
},
|
|
11968
11975
|
"part_number": "M27C1000",
|
|
11969
|
-
"pinout": "
|
|
11976
|
+
"pinout": "DIP32_27C301",
|
|
11970
11977
|
"programming": {
|
|
11971
11978
|
"algorithm": 8,
|
|
11972
11979
|
"chip_id_check": true,
|
|
@@ -11976,7 +11983,8 @@
|
|
|
11976
11983
|
"protect_on_after": false,
|
|
11977
11984
|
"pulse_duration_us": 100
|
|
11978
11985
|
},
|
|
11979
|
-
"support_status": "
|
|
11986
|
+
"support_status": "adapter-required",
|
|
11987
|
+
"unsupported_reason": "adapter required: the shield drives chip pin 22 as CE and pin 24 as OE, but pin map DIP32_27C301 needs other functions on pins [2, 24]. An adapter must move those pins."
|
|
11980
11988
|
},
|
|
11981
11989
|
{
|
|
11982
11990
|
"electrical": {
|
|
@@ -15655,8 +15663,9 @@
|
|
|
15655
15663
|
},
|
|
15656
15664
|
"provenance": "VAR-05 / D-10 \u2014 TI 2532 is a physically real 4KB 24-pin UV-EPROM with a NON-JEDEC pinout (2532 != JEDEC 2732); absent from minipro infoic.xml. The 2516_EPROM.pdf is the TI 2500-series UV-EPROM family datasheet covering the 2516/2532 lineage; VPP=pin 21 / A11=pin 18 / !PD-PGM=pin 20 distinguishes the 2532 from the DIP24_2732 layout. Modeled by the new DIP24_2532 pinout entry. Carries the same UNVERIFIED posture as the 2516 row (no on-hand bench proof).",
|
|
15657
15665
|
"source": "non-upstream-supplement",
|
|
15658
|
-
"support_status": "
|
|
15659
|
-
"
|
|
15666
|
+
"support_status": "adapter-required",
|
|
15667
|
+
"unsupported_reason": "adapter required: the shield drives chip pin 18 as CE and pin 20 as OE, but on the 2532 pin 18 is A11 and pin 20 is PD/PGM. The shield cannot drive A11, so only the lower 2 KB can be addressed, and the program pulse would go to A11. An adapter must move those pins.",
|
|
15668
|
+
"verification_note": "SAFE-04 / D-11: no on-hand 2532 silicon was bench-tested. Non-JEDEC 24-pin oddball; the DIP24_2532 pinout is a tentative leaf layout requiring bench validation. VPP lands on pin 21 (DIP24_2532 vpp-pin) per the TI family datasheet \u2014 the GATE-03 structural VPP guard is satisfied. Socket pin 18 is the shield's CE driver, not an address latch, so host 3.2.4 sent bus line 256 (ROM_CE) for A11; firmware 3.2.1 truncated it to line 0, and later firmware refuses the frame. resolve_chip now refuses the row on its status.",
|
|
15660
15669
|
"verification_status": "UNVERIFIED"
|
|
15661
15670
|
}
|
|
15662
15671
|
],
|
|
@@ -16441,6 +16450,33 @@
|
|
|
16441
16450
|
"pulse_duration_us": 100
|
|
16442
16451
|
},
|
|
16443
16452
|
"support_status": "supported"
|
|
16453
|
+
},
|
|
16454
|
+
{
|
|
16455
|
+
"datasheet": "datasheets/TMM27128AD.pdf",
|
|
16456
|
+
"electrical": {
|
|
16457
|
+
"pin_count": 28,
|
|
16458
|
+
"size_bytes": 16384,
|
|
16459
|
+
"type": "UV-EPROM",
|
|
16460
|
+
"vcc_mv": 5000,
|
|
16461
|
+
"vdd_mv": 6000,
|
|
16462
|
+
"vpp_mv": 12500
|
|
16463
|
+
},
|
|
16464
|
+
"part_number": "TMM27128AD,TMM27128AD-15,TMM27128AD-150,TMM27128AD-20,TMM27128AD-200",
|
|
16465
|
+
"pinout": "DIP28_27128",
|
|
16466
|
+
"programming": {
|
|
16467
|
+
"algorithm": 7,
|
|
16468
|
+
"chip_id_check": true,
|
|
16469
|
+
"chip_id_value": "0x000098d3",
|
|
16470
|
+
"infoic_page_size_raw": 0,
|
|
16471
|
+
"protect_off_before": false,
|
|
16472
|
+
"protect_on_after": false,
|
|
16473
|
+
"pulse_duration_us": 1000
|
|
16474
|
+
},
|
|
16475
|
+
"provenance": "Physically real 28-pin NMOS UV-EPROM (Toshiba TMM27128AD, 16384 x 8), absent from minipro infoic.xml, whose TOSHIBA/KIOXIA section has no 27128-class part. Datasheet attached to henols/firestarter#73 by the reporter, vendored as datasheets/TMM27128AD.pdf (Toshiba pages G-27 to G-36). Page G-27: pin 1 VPP, pin 20 CE, pin 22 OE, pin 26 A13, pin 27 PGM, pin compatible with i27128A (DIP28_27128). Page G-30 HIGH SPEED PROGRAM OPERATION: VCC 5.75/6.0/6.25 V, VPP 12.0/12.5/13.0 V, tPW 0.95/1.0/1.05 ms. Page G-33/G-34: 1 ms PGM pulses verified after each, up to 25 times, then an over-program pulse of 3 times the pulses used. Page G-35 ELECTRIC SIGNATURE MODE: manufacturer code 98, device code D3. Read VCC 5 V (page G-28).",
|
|
16476
|
+
"source": "non-upstream-supplement",
|
|
16477
|
+
"support_status": "supported",
|
|
16478
|
+
"verification_note": "Resolvable for read/info. No working sample has been tested: the chip reported in henols/firestarter#73 was dead. The datasheet program VCC is 6.0 V, but the shield holds VCC at 5 V, and the firmware does not send the over-program pulse.",
|
|
16479
|
+
"verification_status": "UNVERIFIED"
|
|
16444
16480
|
}
|
|
16445
16481
|
],
|
|
16446
16482
|
"WED": [
|
|
@@ -16669,7 +16705,7 @@
|
|
|
16669
16705
|
"type": "EEPROM",
|
|
16670
16706
|
"vcc_mv": 5000,
|
|
16671
16707
|
"vdd_mv": 5000,
|
|
16672
|
-
"vpp_mv":
|
|
16708
|
+
"vpp_mv": 12000
|
|
16673
16709
|
},
|
|
16674
16710
|
"part_number": "W27E257",
|
|
16675
16711
|
"pinout": "DIP28_27256",
|
|
@@ -115,6 +115,16 @@
|
|
|
115
115
|
"ce-pin": [22], "oe-pin": [24], "pgm-pin": [31]
|
|
116
116
|
}
|
|
117
117
|
},
|
|
118
|
+
"DIP32_27C301": {
|
|
119
|
+
"name": "Mask-ROM-compatible 32-pin UV-EPROM (27C301 / 27C1000 — OE on pin 2, A16 on pin 24)",
|
|
120
|
+
"comment": "infoic.xml pin map 12 with protocol 0x08 and variant_lo 0x00. Only MBM27C1000, MBM27C2000, HN27C301G, HN27C301AG and M27C1000 carry it; variant_lo 0x01 in the same map is the JEDEC 27C020 layout. Pin functions are from datasheets/MBM27C1000.pdf (page 4-61 pin assignment, page 4-63 pin description): pin 1 VPP, pin 2 OE, pin 22 CE, pin 24 A16, pin 31 PGM, pin 30 NC. one-rom chip-types.json type 27C301 (aliases 27C1000, 27C100) gives the same OE and A16 pins. JEDEC 27C010/27C020 swap pins 2 and 24, so on DIP32_27C020 these parts drive OE high whenever A16 is 1 (henols/firestarter#70). Pin 30 is A17 for the 256K MBM27C2000 row: <maps> index 12 bonds it, and it is the only bonded pin that has no other function on this layout. No MBM27C2000 datasheet is vendored to confirm it.",
|
|
121
|
+
"pins": {
|
|
122
|
+
"vcc-pin": [32], "gnd-pin": [16], "vpp-pin": [1],
|
|
123
|
+
"address-bus-pins": [12, 11, 10, 9, 8, 7, 6, 5, 27, 26, 23, 25, 4, 28, 29, 3, 24, 30],
|
|
124
|
+
"data-bus-pins": [13, 14, 15, 17, 18, 19, 20, 21],
|
|
125
|
+
"ce-pin": [22], "oe-pin": [2], "pgm-pin": [31]
|
|
126
|
+
}
|
|
127
|
+
},
|
|
118
128
|
"DIP32_27C801": {
|
|
119
129
|
"name": "JEDEC 32-pin UV-EPROM 1M (27C080 / M27C801 — A19 on pin 1, VPP on pin 24)",
|
|
120
130
|
"comment": "Per piersfinlayson/one-rom docs/CHIP-TYPES.md (datasheet-verified): the 8 Mbit 27C080/M27C801 class has 20 address lines (A0-A19) with A19 at pin 1, and VPP at pin 24 shared with /OE — the same OE/VPP sharing DIP28_27512 uses at pin 22. /PGM is pin 22 shared with /CE. Distinct from DIP32_STD (27C040 class: pin 1 = VPP, pin 31 = A18, 19 address lines) and from DIP32_27C020 (pin 31 = PGM). Assigned by resolve_pinout_key to pin_count=32 && pm_idx=12 && proto_id=0x08 && variant_lo=0x03 — the eight 1 MB rows AM27C080, AM27LV080, AT27C080, M27C801 (x2), MX27C8000, MX27C8000A, UPD27C8001. HARDWARE: A19 at pin 1 means socket pin 1 carries an address line, and on Rev 2.x shields socket pin 1 is also the VPP-enable line (JP5 = A19_CUT bridges it to the switched VPP node). JP5 must be cut for these parts, per the shield silkscreen.",
|
|
@@ -165,6 +165,11 @@ _MOVED_PIN_MAPS = {
|
|
|
165
165
|
"chips. 27128/27C128 chips use DIP28_27128 and 27011 chips use "
|
|
166
166
|
"DIP28_27011.",
|
|
167
167
|
),
|
|
168
|
+
"DIP32_27C020": (
|
|
169
|
+
("DIP32_27C301",),
|
|
170
|
+
"Your pin-map override for DIP32_27C020 no longer applies to "
|
|
171
|
+
"27C301/27C1000 chips (OE on pin 2, A16 on pin 24). They use DIP32_27C301.",
|
|
172
|
+
),
|
|
168
173
|
"DIP32_28C512_EEPROM": (
|
|
169
174
|
("DIP32_28C040",),
|
|
170
175
|
"Your pin-map override for DIP32_28C512_EEPROM is not used. "
|
|
@@ -335,8 +335,8 @@ class FirmwareManager:
|
|
|
335
335
|
"""Router: returns (resolved_version, download_url) or (None, None) on failure.
|
|
336
336
|
|
|
337
337
|
channel='stable' → delegates to fetch_latest_release_info (back-compat shim).
|
|
338
|
-
channel='pre' → paginates /releases,
|
|
339
|
-
|
|
338
|
+
channel='pre' → paginates /releases, takes the highest non-draft release by
|
|
339
|
+
PEP 440, stable or pre-release; falls back to stable if none.
|
|
340
340
|
channel='pinned' → fetches /releases/tags/{version} directly.
|
|
341
341
|
""" # noqa: E501
|
|
342
342
|
if channel == "stable":
|
|
@@ -374,10 +374,12 @@ class FirmwareManager:
|
|
|
374
374
|
logger.error(f"Failed to fetch releases for pre-release channel: {e}")
|
|
375
375
|
return None, None
|
|
376
376
|
|
|
377
|
-
#
|
|
377
|
+
# Every non-draft release, stable or pre-release, as `pip --pre`
|
|
378
|
+
# does: a stable 3.2.2 must win over an older 3.1.1b2. Skip
|
|
379
|
+
# unparseable tags.
|
|
378
380
|
candidates = []
|
|
379
381
|
for r in all_releases:
|
|
380
|
-
if
|
|
382
|
+
if r.get("draft"):
|
|
381
383
|
continue
|
|
382
384
|
tag = r.get("tag_name", "")
|
|
383
385
|
try:
|
|
@@ -387,7 +389,7 @@ class FirmwareManager:
|
|
|
387
389
|
|
|
388
390
|
if not candidates:
|
|
389
391
|
logger.info(
|
|
390
|
-
"No
|
|
392
|
+
"No firmware release with a parseable tag — falling back to stable "
|
|
391
393
|
"(matches pip --pre semantics)."
|
|
392
394
|
)
|
|
393
395
|
return self.fetch_latest_release_info(board=board)
|
|
@@ -517,8 +519,13 @@ class FirmwareManager:
|
|
|
517
519
|
avrdude_path_override: str | None,
|
|
518
520
|
avrdude_config_override: str | None,
|
|
519
521
|
target_port: str | None,
|
|
522
|
+
force: bool = False,
|
|
520
523
|
) -> bool:
|
|
521
|
-
"""Internal method to perform the Avrdude flashing process.
|
|
524
|
+
"""Internal method to perform the Avrdude flashing process.
|
|
525
|
+
|
|
526
|
+
`force` adds avrdude's `-F`, which skips the device-signature check,
|
|
527
|
+
for example for a 328PB clone bootloader that reports a 328P signature.
|
|
528
|
+
"""
|
|
522
529
|
start_time = time.time()
|
|
523
530
|
|
|
524
531
|
partno, programmer_id, baud_rate = (
|
|
@@ -594,7 +601,9 @@ class FirmwareManager:
|
|
|
594
601
|
avrdude_config_path=avrdude_config_path,
|
|
595
602
|
)
|
|
596
603
|
|
|
597
|
-
stderr_output, return_code = avrdude.flash_firmware(
|
|
604
|
+
stderr_output, return_code = avrdude.flash_firmware(
|
|
605
|
+
hex_file_path, extra_flags=["-F"] if force else None
|
|
606
|
+
)
|
|
598
607
|
if return_code == 0:
|
|
599
608
|
logger.info(
|
|
600
609
|
f"Firmware successfully updated on {port_to_flash} ({time.time() - start_time:.2f}s)" # noqa: E501
|
|
@@ -741,6 +750,7 @@ class FirmwareManager:
|
|
|
741
750
|
avrdude_config_override: str | None,
|
|
742
751
|
target_port: str | None,
|
|
743
752
|
usb_id: str | None = None,
|
|
753
|
+
force: bool = False,
|
|
744
754
|
) -> bool:
|
|
745
755
|
"""Dispatch to the flasher for this board.
|
|
746
756
|
|
|
@@ -755,6 +765,7 @@ class FirmwareManager:
|
|
|
755
765
|
avrdude_path_override=avrdude_path_override,
|
|
756
766
|
avrdude_config_override=avrdude_config_override,
|
|
757
767
|
target_port=target_port,
|
|
768
|
+
force=force,
|
|
758
769
|
)
|
|
759
770
|
|
|
760
771
|
def manage_firmware_update(
|
|
@@ -778,7 +789,7 @@ class FirmwareManager:
|
|
|
778
789
|
Returns True if an operation (check or install) was successful in some sense, False on major failure.
|
|
779
790
|
|
|
780
791
|
channel='stable' → uses /releases/latest (default, INST-01 non-regression).
|
|
781
|
-
channel='pre' → selects highest pre-release.
|
|
792
|
+
channel='pre' → selects the highest release, stable or pre-release.
|
|
782
793
|
channel='pinned' → uses exact tag from pinned_version.
|
|
783
794
|
""" # noqa: E501
|
|
784
795
|
connected_port, current_version, current_board = self.check_current_firmware(
|
|
@@ -969,6 +980,7 @@ class FirmwareManager:
|
|
|
969
980
|
avrdude_config_override=avrdude_config_override,
|
|
970
981
|
target_port=port_to_use,
|
|
971
982
|
usb_id=usb_id,
|
|
983
|
+
force=bool(force_install),
|
|
972
984
|
)
|
|
973
985
|
# Clean up downloaded file
|
|
974
986
|
if os.path.exists(hex_file):
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Project Name: Firestarter
|
|
3
|
+
Copyright (c) 2024 Henrik Olsson
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted under MIT license.
|
|
6
|
+
|
|
7
|
+
Flash4 (protocol 0x05) erase policy.
|
|
8
|
+
|
|
9
|
+
Firmware 3.2.2 added a software chip erase for protocol 0x05 (the six-cycle
|
|
10
|
+
AA/55/80/AA/55/10 sequence, 5 V only). Older firmware is not safe to send
|
|
11
|
+
that erase to:
|
|
12
|
+
|
|
13
|
+
- 3.0.0b8 to 3.0.0b26 erase a 0x05 part with the VPP regulator and VPE
|
|
14
|
+
switched on: 12 V on a 5 V part.
|
|
15
|
+
- 3.0.0b27 to 3.2.1 answer "not supported".
|
|
16
|
+
|
|
17
|
+
So `FLAG_CAN_ERASE` stays clear for algorithm 5 in the database
|
|
18
|
+
(`erase_support.erase_accepted`), and `write` never carries it. Only the
|
|
19
|
+
`erase` command sets it, for that one command
|
|
20
|
+
(`with_erase_flag`), and `SerialCommunicator.setup_command` refuses the
|
|
21
|
+
command before the operation starts when the firmware is older than
|
|
22
|
+
`ERASE_MIN_FIRMWARE` (`needs_newer_firmware`).
|
|
23
|
+
|
|
24
|
+
Like `jp5_gate.py` and `sdp_capability.py`, this is a pure predicate module:
|
|
25
|
+
no I/O, no environment reads, no serial access.
|
|
26
|
+
|
|
27
|
+
`is_flash4` FAILS OPEN on absent evidence (a wire dict with no `algorithm`
|
|
28
|
+
key is "not flash4"), unlike `jp5_gate` and `sdp_capability`. Refusing every
|
|
29
|
+
chip this predicate cannot classify would break `erase` for chips that are
|
|
30
|
+
not flash4 at all.
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
from __future__ import annotations
|
|
34
|
+
|
|
35
|
+
import re
|
|
36
|
+
from typing import Any, Mapping # noqa: UP035
|
|
37
|
+
|
|
38
|
+
from firestarter.constants import COMMAND_ERASE, FLAG_CAN_ERASE
|
|
39
|
+
|
|
40
|
+
FLASH4_PROTOCOL_ID = 5
|
|
41
|
+
|
|
42
|
+
# The first firmware with the software chip erase for protocol 0x05.
|
|
43
|
+
ERASE_MIN_FIRMWARE = (3, 2, 2)
|
|
44
|
+
|
|
45
|
+
_FIRMWARE_REFUSAL_FORMAT = (
|
|
46
|
+
"Erasing this chip needs firmware {minimum} or later; this board runs "
|
|
47
|
+
"{version}. Update it with 'firestarter fw --install'."
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def is_flash4(programmer_data: Mapping[str, Any] | None) -> bool:
|
|
52
|
+
"""True when the wire dict's `algorithm` value is the flash4 protocol id.
|
|
53
|
+
|
|
54
|
+
The comparison is against `algorithm`, not `flags & FLAG_CAN_ERASE`: the
|
|
55
|
+
flag is also clear for UV-EPROM and SRAM parts, so a flag-based
|
|
56
|
+
predicate would widen this past its flash4-only scope.
|
|
57
|
+
|
|
58
|
+
Returns False for a missing, `None`, or empty `programmer_data`, and for
|
|
59
|
+
a dict with no `algorithm` key.
|
|
60
|
+
"""
|
|
61
|
+
if not programmer_data:
|
|
62
|
+
return False
|
|
63
|
+
return programmer_data.get("algorithm") == FLASH4_PROTOCOL_ID
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def with_erase_flag(programmer_data: Mapping[str, Any]) -> dict[str, Any]:
|
|
67
|
+
"""A copy of `programmer_data` with `FLAG_CAN_ERASE` set, for `erase` only."""
|
|
68
|
+
data = dict(programmer_data)
|
|
69
|
+
data["flags"] = int(data.get("flags") or 0) | FLAG_CAN_ERASE
|
|
70
|
+
return data
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def _version_tuple(version: str | None) -> tuple[int, int, int] | None:
|
|
74
|
+
match = re.match(r"(\d+)\.(\d+)\.(\d+)", version or "")
|
|
75
|
+
if not match:
|
|
76
|
+
return None
|
|
77
|
+
return (int(match.group(1)), int(match.group(2)), int(match.group(3)))
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def needs_newer_firmware(
|
|
81
|
+
command: Mapping[str, Any], firmware_version: str | None
|
|
82
|
+
) -> bool:
|
|
83
|
+
"""True when `command` is a flash4 erase that `firmware_version` cannot run safely.
|
|
84
|
+
|
|
85
|
+
Only an erase command that carries `FLAG_CAN_ERASE` for a flash4 part is
|
|
86
|
+
affected; every other command returns False. A version that cannot be
|
|
87
|
+
parsed counts as too old, because the 3.0.0 pre-releases with the 12 V
|
|
88
|
+
erase are older than every version this check accepts. A pre-release
|
|
89
|
+
or development build of 3.2.2 (`3.2.2rc1`, `3.2.2.dev5`) counts as 3.2.2.
|
|
90
|
+
"""
|
|
91
|
+
if command.get("cmd") != COMMAND_ERASE or not is_flash4(command):
|
|
92
|
+
return False
|
|
93
|
+
if not int(command.get("flags") or 0) & FLAG_CAN_ERASE:
|
|
94
|
+
return False
|
|
95
|
+
parsed = _version_tuple(firmware_version)
|
|
96
|
+
return parsed is None or parsed < ERASE_MIN_FIRMWARE
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def firmware_refusal_text(firmware_version: str | None) -> str:
|
|
100
|
+
"""The one-line refusal for a flash4 erase on firmware that is too old."""
|
|
101
|
+
return _FIRMWARE_REFUSAL_FORMAT.format(
|
|
102
|
+
minimum=".".join(str(n) for n in ERASE_MIN_FIRMWARE),
|
|
103
|
+
version=firmware_version or "an unknown version",
|
|
104
|
+
)
|
|
@@ -12,6 +12,7 @@ from typing import Dict, List # noqa: UP035
|
|
|
12
12
|
from firestarter import jumper_table
|
|
13
13
|
from firestarter.database import EpromDatabase, format_mv
|
|
14
14
|
from firestarter.erase_support import erase_accepted, is_electrically_erasable
|
|
15
|
+
from firestarter.flash4_erase_gate import FLASH4_PROTOCOL_ID
|
|
15
16
|
from firestarter.vpp_display import shows_programming_vpp
|
|
16
17
|
|
|
17
18
|
logger = logging.getLogger("EpromSpecBuilder")
|
|
@@ -19,6 +20,7 @@ logger = logging.getLogger("EpromSpecBuilder")
|
|
|
19
20
|
CAN_ERASE_YES = "yes (electrically erasable)"
|
|
20
21
|
CAN_ERASE_UV_ONLY = "no (UV erase only)"
|
|
21
22
|
CAN_ERASE_NOT_SUPPORTED = "no (erase is not supported for this chip)"
|
|
23
|
+
CAN_ERASE_FLASH4 = "yes (needs firmware 3.2.2 or later)"
|
|
22
24
|
|
|
23
25
|
|
|
24
26
|
class EpromSpecBuilder:
|
|
@@ -524,6 +526,11 @@ class EpromSpecBuilder:
|
|
|
524
526
|
etype, eprom_data.get("protocol-id"), eprom_data.get("pin-map")
|
|
525
527
|
):
|
|
526
528
|
output_data["can_erase_str"] = CAN_ERASE_YES
|
|
529
|
+
elif is_electrically_erasable(etype) and (
|
|
530
|
+
eprom_data.get("protocol-id") == FLASH4_PROTOCOL_ID
|
|
531
|
+
):
|
|
532
|
+
# `erase` sets FLAG_CAN_ERASE for flash4 itself (flash4_erase_gate).
|
|
533
|
+
output_data["can_erase_str"] = CAN_ERASE_FLASH4
|
|
527
534
|
elif is_electrically_erasable(etype):
|
|
528
535
|
output_data["can_erase_str"] = CAN_ERASE_NOT_SUPPORTED
|
|
529
536
|
elif etype == "UV-EPROM":
|
|
@@ -401,6 +401,16 @@ JUMPER_TABLE: Mapping[str, JumperEntry] = {
|
|
|
401
401
|
rev20_jp4=Jp4Rev20.OPEN,
|
|
402
402
|
rev22_jp4=Jp4Rev22.NO_JUMPER,
|
|
403
403
|
),
|
|
404
|
+
# Pins 1, 28, 30 and 32 have the DIP32_27C020 functions; only pins 2 and 24 differ.
|
|
405
|
+
"DIP32_27C301": JumperEntry(
|
|
406
|
+
vpp_lands=VppLanding.SOCKET_1,
|
|
407
|
+
pin1_signal="VPP",
|
|
408
|
+
jp1=Jp1.A13,
|
|
409
|
+
jp2=Jp2.A17,
|
|
410
|
+
jp3=Jp3.PIN32,
|
|
411
|
+
rev20_jp4=Jp4Rev20.OPEN,
|
|
412
|
+
rev22_jp4=Jp4Rev22.NO_JUMPER,
|
|
413
|
+
),
|
|
404
414
|
# VPP shares OE. Chip pin 1 is A19. The JP5 gate (jp5_gate.py) controls write and erase.
|
|
405
415
|
"DIP32_27C801": JumperEntry(
|
|
406
416
|
vpp_lands=VppLanding.OE,
|
|
@@ -20,6 +20,7 @@ import serial.serialutil
|
|
|
20
20
|
import serial.tools.list_ports
|
|
21
21
|
|
|
22
22
|
import firestarter.codec as codec
|
|
23
|
+
import firestarter.flash4_erase_gate as flash4_erase_gate
|
|
23
24
|
import firestarter.transport_counters as transport_counters
|
|
24
25
|
from firestarter.config import ConfigManager # Assuming ConfigManager is refactored
|
|
25
26
|
from firestarter.constants import (
|
|
@@ -957,9 +958,17 @@ class SerialCommunicator:
|
|
|
957
958
|
# to major=3 later. Set FIRESTARTER_DEV_ALLOW_PRE_V12=1 to bypass when # noqa: E501
|
|
958
959
|
# bench-testing a current host against a historical (v2.x) firmware build. # noqa: E501
|
|
959
960
|
SerialCommunicator._validate_firmware_version(
|
|
960
|
-
version_match.group(0),
|
|
961
|
+
version_match.group(0).rstrip("."),
|
|
961
962
|
allow_pre_v12=os.environ.get("FIRESTARTER_DEV_ALLOW_PRE_V12") == "1",
|
|
962
963
|
)
|
|
964
|
+
# A flash4 erase on firmware older than 3.2.2 reaches either a
|
|
965
|
+
# 12 V erase (3.0.0b8-b26) or a "not supported" answer.
|
|
966
|
+
if flash4_erase_gate.needs_newer_firmware(command_to_send, identity):
|
|
967
|
+
raise FirmwareOutdatedError(
|
|
968
|
+
flash4_erase_gate.firmware_refusal_text(
|
|
969
|
+
identity.split(":")[0] if identity else None
|
|
970
|
+
)
|
|
971
|
+
)
|
|
963
972
|
|
|
964
973
|
# Shield-revision gate — ordered after the version check because
|
|
965
974
|
# firmware old enough to fail that check cannot be trusted to have
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: firestarter
|
|
3
|
-
Version: 3.2.
|
|
3
|
+
Version: 3.2.6
|
|
4
4
|
Summary: EPROM programmer software for the Relatively Universal ROM Programmer
|
|
5
5
|
Author-email: Henrik Olsson <henols@gmail.com>
|
|
6
6
|
Project-URL: Homepage, https://github.com/henols/firestarter_app
|
|
@@ -595,6 +595,8 @@
|
|
|
595
595
|
Eprom Info
|
|
596
596
|
Name: MBM27C1000P,MBM27C1000
|
|
597
597
|
Manufacturer: FUJITSU
|
|
598
|
+
Support status: adapter-required
|
|
599
|
+
Reason: adapter required: the shield drives chip pin 22 as CE and pin 24 as OE, but pin map DIP32_27C301 needs other functions on pins [2, 24]. An adapter must move those pins.
|
|
598
600
|
Number of pins: 32
|
|
599
601
|
Memory size 0x20000
|
|
600
602
|
Type: UV-EPROM
|
|
@@ -610,14 +612,14 @@
|
|
|
610
612
|
32-DIP package
|
|
611
613
|
-----v-----
|
|
612
614
|
VPP -| 1 32 |- VCC
|
|
613
|
-
|
|
615
|
+
OE -| 2 31 |- PGM
|
|
614
616
|
A15 -| 3 30 |- A17
|
|
615
617
|
A12 -| 4 29 |- A14
|
|
616
618
|
A7 -| 5 28 |- A13
|
|
617
619
|
A6 -| 6 27 |- A8
|
|
618
620
|
A5 -| 7 26 |- A9
|
|
619
621
|
A4 -| 8 25 |- A11
|
|
620
|
-
A3 -| 9 24 |-
|
|
622
|
+
A3 -| 9 24 |- A16
|
|
621
623
|
A2 -| 10 23 |- A10
|
|
622
624
|
A1 -| 11 22 |- CE
|
|
623
625
|
A0 -| 12 21 |- D7
|
|
@@ -1441,6 +1443,7 @@
|
|
|
1441
1443
|
| TC54256AF,TC54256AP | TOSHIBA/KIOXIA | 28 | 0x98C4 | UV-EPROM | 12.0v|
|
|
1442
1444
|
| TC57256D | TOSHIBA/KIOXIA | 28 | 0x9845 | UV-EPROM | 13.0v|
|
|
1443
1445
|
| TC57512AD | TOSHIBA/KIOXIA | 28 | 0x9885 | UV-EPROM | 13.0v|
|
|
1446
|
+
| TMM27128AD,TMM27128…| TOSHIBA/KIOXIA | 28 | 0x98D3 | UV-EPROM | 12.5v|
|
|
1444
1447
|
| WE128K8 | WED | 32 | | Flash/EEPROM| - |
|
|
1445
1448
|
| WE256K8 | WED | 32 | | Flash/EEPROM| - |
|
|
1446
1449
|
| WE512K8 | WED | 32 | | Flash/EEPROM| - |
|
|
@@ -1450,7 +1453,7 @@
|
|
|
1450
1453
|
| W27C04,W27C040,W27E…| WINBOND | 32 | 0xDA86 | EEPROM | 12.0v|
|
|
1451
1454
|
| W27C257 | WINBOND | 28 | 0xDA02 | EEPROM | 12.0v|
|
|
1452
1455
|
| W27C512,W27E512 | WINBOND | 28 | 0xDA08 | EEPROM | 12.0v|
|
|
1453
|
-
| W27E257 | WINBOND | 28 | 0xDA02 | EEPROM |
|
|
1456
|
+
| W27E257 | WINBOND | 28 | 0xDA02 | EEPROM | 12.0v|
|
|
1454
1457
|
| W29C010,W29C011,W29…| WINBOND | 32 | 0xDAC1 | Flash/EEPROM| - |
|
|
1455
1458
|
| W29C020,W29C020C,W2…| WINBOND | 32 | 0xDA45 | Flash/EEPROM| - |
|
|
1456
1459
|
| W29C040,W29C042 | WINBOND | 32 | 0xDA46 | Flash/EEPROM| - |
|
|
@@ -1579,7 +1582,7 @@
|
|
|
1579
1582
|
| W27C04,W27C040,W27E…| WINBOND | 32 | 0xDA86 | EEPROM | 12.0v|
|
|
1580
1583
|
| W27C257 | WINBOND | 28 | 0xDA02 | EEPROM | 12.0v|
|
|
1581
1584
|
| W27C512,W27E512 | WINBOND | 28 | 0xDA08 | EEPROM | 12.0v|
|
|
1582
|
-
| W27E257 | WINBOND | 28 | 0xDA02 | EEPROM |
|
|
1585
|
+
| W27E257 | WINBOND | 28 | 0xDA02 | EEPROM | 12.0v|
|
|
1583
1586
|
+---------------------+------------------+------+------------+-------------+------+
|
|
1584
1587
|
|
|
1585
1588
|
'''
|