1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
use crate::config::{NvmRegion, RamRegion, TargetDescriptionSource};
use crate::error;
use std::ops::Range;

/// Describes any error that happened during the or in preparation for the flashing procedure.
#[derive(thiserror::Error, Debug)]
pub enum FlashError {
    /// No flash memory contains the entire requested memory range.
    #[error(
        "No flash memory contains the entire requested memory range {start:#010x}..{end:#10x}."
    )]
    NoSuitableNvm {
        /// The start of the requested memory range.
        start: u64,
        /// The end of the requested memory range.
        end: u64,
        /// The source of this target description (was it a built in target or one loaded externally and from what file path?).
        description_source: TargetDescriptionSource,
    },
    /// Erasing the full chip flash failed.
    #[error("Failed to erase the whole chip.")]
    ChipEraseFailed {
        /// The source error of this error.
        source: Box<dyn std::error::Error + 'static + Send + Sync>,
    },
    /// Erasing the given flash sector failed.
    #[error("Failed to erase flash sector at address {sector_address:#010x}.")]
    EraseFailed {
        /// The address of the sector that should have been erased.
        sector_address: u64,
        /// The source error of this error.
        #[source]
        source: Box<dyn std::error::Error + 'static + Send + Sync>,
    },
    /// Writing the given page failed.
    #[error("The page write of the page at address {page_address:#010x} failed.")]
    PageWrite {
        /// The address of the page that should have been written.
        page_address: u64,
        /// The source error of this error.
        #[source]
        source: Box<dyn std::error::Error + 'static + Send + Sync>,
    },
    /// Initializing the flash algorithm failed.
    #[error("The initialization of the flash algorithm failed.")]
    Init(#[source] Box<dyn std::error::Error + 'static + Send + Sync>),
    /// Uninizializing the flash algorithm failed.
    #[error("The uninitialization of the flash algorithm failed.")]
    Uninit(#[source] Box<dyn std::error::Error + 'static + Send + Sync>),
    /// This target does not support full chip flash erases.
    #[error("The chip erase routine is not supported with the given flash algorithm.")]
    ChipEraseNotSupported,
    /// Calling the given routine returned the given error code.
    #[error("The execution of '{name}' failed with code {error_code}. This might indicate a problem with the flash algorithm.")]
    RoutineCallFailed {
        /// The name of the routine that was called.
        name: &'static str,
        /// The error code the called routine returned.
        error_code: u32,
    },
    /// The given address was not contained in the given NVM region.
    #[error("{address:#010x} is not contained in {region:?}")]
    AddressNotInRegion {
        /// The address which was not contained in `region`.
        address: u32,
        /// The region which did not contain `address`.
        region: NvmRegion,
    },
    /// An error occurred during the interaction with the core.
    #[error("Something during the interaction with the core went wrong")]
    Core(#[from] error::Error),
    /// The RAM contents did not match the flash algorithm.
    #[error(
        "The RAM contents did not match the expected contents after loading the flash algorithm."
    )]
    FlashAlgorithmNotLoaded,
    /// Failed to load the flash algorithm into RAM at given address. This can happen if there is not enough space.
    ///
    /// Check the algorithm code and settings before you try again.
    #[error(
        "Failed to load flash algorithm into RAM at address {address:08X?}. Is there space for the algorithm header?"
    )]
    InvalidFlashAlgorithmLoadAddress {
        /// The address where the algorithm was supposed to be loaded to.
        address: u64,
    },
    /// The given page size is not valid. Only page sizes multiples of 4 bytes are allowed.
    #[error("Invalid page size {size:08X?}. Must be a multiple of 4 bytes.")]
    InvalidPageSize {
        /// The size of the page in bytes.
        size: u32,
    },
    // TODO: Warn at YAML parsing stage.
    // TODO: 1 Add information about flash (name, address)
    // TODO: 2 Add source of target definition (built-in, yaml)
    /// No flash algorithm was linked to this target.
    #[error("Trying to write flash, but no suitable (default) flash loader algorithm is linked to the given target: {name} .")]
    NoFlashLoaderAlgorithmAttached {
        /// The name of the chip.
        name: String,
    },
    /// More than one matching flash algorithm was found for the given memory range and all of them is marked as default.
    #[error("Trying to write flash, but found more than one suitable flash loader algorithim marked as default for {region:?}.")]
    MultipleDefaultFlashLoaderAlgorithms {
        /// The region which matched more than one flash algorithm.
        region: NvmRegion,
    },
    /// More than one matching flash algorithm was found for the given memory range and none of them is marked as default.
    #[error("Trying to write flash, but found more than one suitable flash algorithims but none marked as default for {region:?}.")]
    MultipleFlashLoaderAlgorithmsNoDefault {
        /// The region which matched more than one flash algorithm.
        region: NvmRegion,
    },
    /// Flash content verification failed.
    #[error("Flash content verification failed.")]
    Verify,
    // TODO: 1 Add source of target definition
    // TOOD: 2 Do this at target load time.
    /// The given chip has no RAM defined.
    #[error("No RAM defined for target: {name}.")]
    NoRamDefined {
        /// The name of the chip.
        name: String,
    },
    /// The given flash algorithm did not have a leng multiple of 4 bytes.
    ///
    /// This means that the flash algorithm that was loaded is broken.
    #[error("Flash algorithm {name} does not have a length that is 4 byte aligned.")]
    InvalidFlashAlgorithmLength {
        /// The name of the flash algorithm.
        name: String,
        /// The source of the flash algorithm (was it a built in target or one loaded externally and from what file path?).
        algorithm_source: Option<TargetDescriptionSource>,
    },
    /// Two blocks of data overlap each other which means the loaded binary is broken.
    ///
    /// Please check your data and try again.
    #[error("Adding data for addresses {added_addresses:08X?} overlaps previously added data for addresses {existing_addresses:08X?}.")]
    DataOverlaps {
        /// The address range that was tried to be added.
        added_addresses: Range<u64>,
        /// The address range that was already present.
        existing_addresses: Range<u64>,
    },
    /// No core can access this NVM region.
    #[error("No core can access the NVM region {0:?}.")]
    NoNvmCoreAccess(NvmRegion),
    /// No core can access this RAM region.
    #[error("No core can access the ram region {0:?}.")]
    NoRamCoreAccess(RamRegion),
    /// The register value supplied for this flash algorithm is out of the supported range.
    #[error("The register value {0:08X?} is out of the supported range.")]
    RegisterValueNotSupported(u64),
}