synth_backend/
vector_table.rs1use synth_core::Result;
6
7#[derive(Debug, Clone)]
9pub struct VectorEntry {
10 pub name: String,
12 pub address: u32,
14 pub weak: bool,
16}
17
18pub struct VectorTable {
20 pub initial_sp: u32,
22 pub reset_handler: u32,
24 pub handlers: Vec<VectorEntry>,
26}
27
28impl VectorTable {
29 #[allow(clippy::vec_init_then_push)]
31 pub fn new_cortex_m(stack_top: u32) -> Self {
32 let mut handlers = Vec::new();
33
34 handlers.push(VectorEntry {
36 name: "NMI_Handler".to_string(),
37 address: 0,
38 weak: true,
39 });
40 handlers.push(VectorEntry {
41 name: "HardFault_Handler".to_string(),
42 address: 0,
43 weak: false, });
45 handlers.push(VectorEntry {
46 name: "MemManage_Handler".to_string(),
47 address: 0,
48 weak: true,
49 });
50 handlers.push(VectorEntry {
51 name: "BusFault_Handler".to_string(),
52 address: 0,
53 weak: true,
54 });
55 handlers.push(VectorEntry {
56 name: "UsageFault_Handler".to_string(),
57 address: 0,
58 weak: true,
59 });
60 for _ in 0..4 {
62 handlers.push(VectorEntry {
63 name: "Reserved".to_string(),
64 address: 0,
65 weak: true,
66 });
67 }
68 handlers.push(VectorEntry {
69 name: "SVC_Handler".to_string(),
70 address: 0,
71 weak: true,
72 });
73 handlers.push(VectorEntry {
74 name: "DebugMon_Handler".to_string(),
75 address: 0,
76 weak: true,
77 });
78 handlers.push(VectorEntry {
79 name: "Reserved".to_string(),
80 address: 0,
81 weak: true,
82 });
83 handlers.push(VectorEntry {
84 name: "PendSV_Handler".to_string(),
85 address: 0,
86 weak: true,
87 });
88 handlers.push(VectorEntry {
89 name: "SysTick_Handler".to_string(),
90 address: 0,
91 weak: true,
92 });
93
94 for i in 0..16 {
97 handlers.push(VectorEntry {
98 name: format!("IRQ{}_Handler", i),
99 address: 0,
100 weak: true,
101 });
102 }
103
104 Self {
105 initial_sp: stack_top,
106 reset_handler: 0,
107 handlers,
108 }
109 }
110
111 pub fn generate_binary(&self) -> Result<Vec<u8>> {
113 let mut data = Vec::new();
114
115 data.extend_from_slice(&self.initial_sp.to_le_bytes());
117
118 let reset_addr = self.reset_handler | 1;
121 data.extend_from_slice(&reset_addr.to_le_bytes());
122
123 for handler in &self.handlers {
125 let addr = if handler.address != 0 {
126 handler.address | 1 } else {
128 0 };
130 data.extend_from_slice(&addr.to_le_bytes());
131 }
132
133 Ok(data)
134 }
135
136 pub fn generate_assembly(&self) -> String {
138 let mut asm = String::new();
139
140 asm.push_str(" .syntax unified\n");
141 asm.push_str(" .cpu cortex-m3\n");
142 asm.push_str(" .fpu softvfp\n");
143 asm.push_str(" .thumb\n\n");
144
145 asm.push_str(" .section .isr_vector,\"a\",%progbits\n");
146 asm.push_str(" .type g_pfnVectors, %object\n");
147 asm.push_str(" .size g_pfnVectors, .-g_pfnVectors\n\n");
148
149 asm.push_str("g_pfnVectors:\n");
150 asm.push_str(" .word _estack\n");
151 asm.push_str(" .word Reset_Handler\n");
152
153 for handler in &self.handlers {
154 asm.push_str(&format!(" .word {}\n", handler.name));
155 }
156
157 asm.push('\n');
158
159 asm.push_str(" .weak NMI_Handler\n");
161 asm.push_str(" .thumb_set NMI_Handler,Default_Handler\n\n");
162
163 for handler in &self.handlers {
164 if handler.weak && handler.name != "Reserved" {
165 asm.push_str(&format!(" .weak {}\n", handler.name));
166 asm.push_str(&format!(
167 " .thumb_set {},Default_Handler\n",
168 handler.name
169 ));
170 }
171 }
172
173 asm.push('\n');
174 asm.push_str(" .section .text.Default_Handler,\"ax\",%progbits\n");
175 asm.push_str("Default_Handler:\n");
176 asm.push_str("Infinite_Loop:\n");
177 asm.push_str(" b Infinite_Loop\n");
178 asm.push_str(" .size Default_Handler, .-Default_Handler\n");
179
180 asm
181 }
182
183 pub fn size_bytes(&self) -> usize {
185 4 + 4 + (self.handlers.len() * 4)
187 }
188}
189
190#[cfg(test)]
191mod tests {
192 use super::*;
193
194 #[test]
195 fn test_vector_table_creation() {
196 let vt = VectorTable::new_cortex_m(0x20010000);
197 assert_eq!(vt.initial_sp, 0x20010000);
198 assert!(vt.handlers.len() > 15); }
200
201 #[test]
202 fn test_vector_table_binary_generation() {
203 let mut vt = VectorTable::new_cortex_m(0x20010000);
204 vt.reset_handler = 0x08000100;
205
206 let binary = vt.generate_binary().unwrap();
207
208 let sp = u32::from_le_bytes([binary[0], binary[1], binary[2], binary[3]]);
210 assert_eq!(sp, 0x20010000);
211
212 let reset = u32::from_le_bytes([binary[4], binary[5], binary[6], binary[7]]);
214 assert_eq!(reset, 0x08000101); }
216
217 #[test]
218 fn test_vector_table_size() {
219 let vt = VectorTable::new_cortex_m(0x20010000);
220 let size = vt.size_bytes();
221 let binary = vt.generate_binary().unwrap();
222 assert_eq!(size, binary.len());
223 }
224
225 #[test]
226 fn test_assembly_generation() {
227 let vt = VectorTable::new_cortex_m(0x20010000);
228 let asm = vt.generate_assembly();
229
230 assert!(asm.contains(".syntax unified"));
231 assert!(asm.contains("g_pfnVectors:"));
232 assert!(asm.contains("Reset_Handler"));
233 assert!(asm.contains("Default_Handler"));
234 }
235
236 #[test]
237 fn test_thumb_mode_bit() {
238 let mut vt = VectorTable::new_cortex_m(0x20010000);
239 vt.reset_handler = 0x08000100; vt.handlers[0].address = 0x08000200;
241
242 let binary = vt.generate_binary().unwrap();
243
244 let reset = u32::from_le_bytes([binary[4], binary[5], binary[6], binary[7]]);
246 assert_eq!(reset & 1, 1);
247
248 let handler = u32::from_le_bytes([binary[8], binary[9], binary[10], binary[11]]);
250 assert_eq!(handler & 1, 1);
251 }
252}