diff --git a/.ginit_old b/.ginit_old new file mode 100644 index 0000000000000000000000000000000000000000..90bca3d74a818810eb71148f4dde17a564b239fb --- /dev/null +++ b/.ginit_old @@ -0,0 +1,8 @@ +target remote :3333 + +monitor reset init +monitor arm semihosting enable +monitor tpiu config internal /tmp/itm.log uart off 84000000 +monitor itm port 0 on +load +monitor reset init diff --git a/.vscode/launch.json b/.vscode/launch.json index 12dae9b3574a60eb351821f4e774703ece40a1e4..ec932b93fd374979e88b33e7a432da27a8c54e89 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -238,5 +238,166 @@ ], "cwd": "${workspaceRoot}" }, + { + "type": "gdb", + "request": "attach", + "name": "bare2 Release", + "gdbpath": "/usr/bin/arm-none-eabi-gdb", + "executable": "./target/thumbv7em-none-eabihf/release/examples/bare2", + "target": ":3333", + "remote": true, + "autorun": [ + "monitor reset init", + "monitor arm semihosting enable", + "monitor tpiu config internal /tmp/itm.log uart off 64000000", + "monitor itm port 0 on", + "load", + "monitor reset init" + ], + "cwd": "${workspaceRoot}" + }, + { + "type": "gdb", + "request": "attach", + "name": "usart_dma_tx", + "gdbpath": "/usr/bin/arm-none-eabi-gdb", + "executable": "./target/thumbv7em-none-eabihf/debug/examples/usart_dma_tx", + "target": ":3333", + "remote": true, + "autorun": [ + "monitor reset init", + "monitor arm semihosting enable", + "monitor tpiu config internal /tmp/itm.log uart off 16000000", + "monitor itm port 0 on", + "load", + "monitor reset" + ], + "cwd": "${workspaceRoot}" + }, + { + "type": "gdb", + "request": "attach", + "name": "usart_dma_rx", + "gdbpath": "/usr/bin/arm-none-eabi-gdb", + "executable": "./target/thumbv7em-none-eabihf/debug/examples/usart_dma_rx", + "target": ":3333", + "remote": true, + "autorun": [ + "monitor reset init", + "monitor arm semihosting enable", + "monitor tpiu config internal /tmp/itm.log uart off 16000000", + "monitor itm port 0 on", + "load", + "monitor reset" + ], + "cwd": "${workspaceRoot}" + }, + { + "type": "gdb", + "request": "attach", + "name": "usart_loopback", + "gdbpath": "/usr/bin/arm-none-eabi-gdb", + "executable": "./target/thumbv7em-none-eabihf/debug/examples/usart_loopback", + "target": ":3333", + "remote": true, + "autorun": [ + "monitor reset init", + "monitor arm semihosting enable", + "monitor tpiu config internal /tmp/itm.log uart off 16000000", + "monitor itm port 0 on", + "load", + "monitor reset" + ], + "cwd": "${workspaceRoot}" + }, + { + "type": "gdb", + "request": "attach", + "name": "pwm", + "gdbpath": "/usr/bin/arm-none-eabi-gdb", + "executable": "./target/thumbv7em-none-eabihf/debug/examples/pwm", + "target": ":3333", + "remote": true, + "autorun": [ + "monitor reset init", + "monitor arm semihosting enable", + "monitor tpiu config internal /tmp/itm.log uart off 16000000", + "monitor itm port 0 on", + "load", + ], + "cwd": "${workspaceRoot}" + }, + { + "type": "gdb", + "request": "attach", + "name": "clk_out_itm", + "gdbpath": "/usr/bin/arm-none-eabi-gdb", + "executable": "./target/thumbv7em-none-eabihf/debug/examples/clk_out_itm", + "target": ":3333", + "remote": true, + "autorun": [ + "monitor reset init", + "monitor arm semihosting enable", + "monitor tpiu config internal /tmp/itm.log uart off 16000000", + "monitor itm port 0 on", + "load", + "monitor reset" + ], + "cwd": "${workspaceRoot}" + }, + { + "type": "cortex-debug", + "request": "launch", + "servertype": "openocd", + "name": "c bare1", + "executable": "./target/thumbv7em-none-eabihf/debug/examples/bare1", + "configFiles": [ + "interface/stlink.cfg", + "target/stm32f4x.cfg" + ], + "cwd": "${workspaceRoot}", + "swoConfig": { + "enabled": true, + "cpuFrequency": 16000000, + "swoFrequency": 1000000, + "source": "probe", + "decoders": [ + { + "type": "console", + "label": "Name", + "port": 0 + } + ] + } + }, + { + "type": "cortex-debug", + "request": "launch", + "servertype": "openocd", + "name": "c bare6", + "executable": "./target/thumbv7em-none-eabihf/debug/examples/bare6", + "configFiles": [ + "interface/stlink.cfg", + "target/stm32f4x.cfg" + ], + "postLaunchCommands": [ + "monitor tpiu config internal /tmp/itm.log uart off 16000000", + "monitor itm port 0 on" + ], + "swoConfig": { + "enabled": true, + "cpuFrequency": 16000000, + "swoFrequency": 1000000, + "source": "probe", + "decoders": [ + { + "type": "console", + "label": "Name", + "port": 0 + } + ] + }, + "cwd": "${workspaceRoot}" + } ] } \ No newline at end of file diff --git a/Makefile b/Makefile index f328ca86f08f4f3ce034cc9a0cffdd52ba334d66..89989a7b593da7071efcf10ef054786fbc60904b 100644 --- a/Makefile +++ b/Makefile @@ -1,15 +1,19 @@ TARGETS = bare0 bare1 bare2 bare3 bare4 bare5 bare6 -DIR = target/thumbv7em-none-eabihf/debug/examples/ -ELFS = $(addprefix $(DIR), $(TARGETS)) +DEV = target/thumbv7em-none-eabihf/debug/examples/ +REL = target/thumbv7em-none-eabihf/release/examples/ +ELFS = $(addprefix $(DEV), $(TARGETS)) EELFS = $(addsuffix .elf, $(ELFS)) +ELFSR = $(addprefix $(REL), $(TARGETS)) +EELFSR = $(addsuffix .elf, $(ELFSR)) .PHONY: all -all: xargo $(EELFS) +all: xargo $(EELFS) $(EELFSR) xargo: - xargo build --examples + xargo build --examples + xargo build --release --examples %.elf : % cp $< $@ diff --git a/examples/bare2.rs b/examples/bare2.rs index bf49b9243f1e1c2919b7068a0a8379e18ab2af22..be78e88cccffbe7f84d3d4823b9093d6675adc08 100644 --- a/examples/bare2.rs +++ b/examples/bare2.rs @@ -30,6 +30,41 @@ fn main() { } } +// 1. build and run the application (debug build) +// start ITM tracing to console *version 0.1.1* +// > itmdump /tmp/itm.log +// or alternatively *version 0.2.0* +// > mkfifo /tmp/itm.log +// > itmdump -f /tmp/itm.log -F +// +// start openocd (in my case...) +// > openocd -f interface/stlink.cfg -f target/stm32f4x.cfg +// +// what is the output in the ITM console +// ** your answer here ** +// +// estimate the frequency of the output, give freq in hz +// ** your answer here ** +// +// commit your answers (bare2_1) +// +// 2. rebuild and run in release mode +// estimate the frequency of the output, give freq in hz +// ** your answer here ** +// +// estimate the ratio between debug/release optimized code +// (speedup) +// ** your answer here ** +// +// commit your answers (bare2_2) +// +// 3. optional +// inspect the generated binaries, and try stepping through the code +// for both debug and release binaries. How do they differ +// ** your answer here ** +// +// commit your answers (bare2_3) + // As we are not using interrupts, we just register a dummy catch all handler #[link_section = ".vector_table.interrupts"] #[used] diff --git a/examples/bare3.rs b/examples/bare3.rs index 964a4fb9da7b2350eca6d51511997f38feff3c14..272d9fbebbcaf788f36c98035b24ccbd8f87bf4c 100644 --- a/examples/bare3.rs +++ b/examples/bare3.rs @@ -7,22 +7,86 @@ extern crate cortex_m; extern crate cortex_m_rt; +use core::str; + #[macro_use] extern crate cortex_m_debug; fn main() { let s = "ABCD"; - ipln!("s = {:?}", s); + let bs = s.as_bytes(); + + ipln!("s = {}", s); + ipln!("bs = {:?}", bs); - // iterate over the byte repr. of s - for c in s.as_bytes() { + ipln!("iterate over slice"); + for c in bs { ip!("{},", c) } + let mut a = [65u8; 4]; + //let mut a = [0u8; 4]; + ipln!(); + ipln!("iterate iterate using (raw) indexing"); + for i in 0..s.len() { + ip!("{},", bs[i]); + } + ipln!(); + ipln!("a = {}", str::from_utf8(&a).unwrap()); loop {} } +// 1. build and run the application (debug build) +// start ITM tracing to console *version 0.1.1* +// > itmdump /tmp/itm.log +// or alternatively *version 0.2.0* +// > mkfifo /tmp/itm.log +// > itmdump -f /tmp/itm.log -F +// +// start openocd (in my case...) +// > openocd -f interface/stlink.cfg -f target/stm32f4x.cfg +// +// what is the output in the ITM console +// ** your answer here ** +// +// what is the type of `s` +// ** your answer here ** +// +// what is the type of `bs` +// ** your answer here ** +// +// what is the type of `c` +// ** your answer here ** +// +// what is the type of `a` +// ** your answer here ** +// +// what is the type of `i` +// ** your answer here ** +// +// commit your answers (bare3_1) +// +// 2. make types of `s`, `bs`, `c`, `a`, `i` explicit +// +// commit your answers (bare3_2) +// +// 3. uncomment line 28 (let mut a = [0u8; 4];) +// what happens and why +// ** your answer here ** +// +// commit your answers (bare3_3) +// +// 4. alter the program so that the data from `bs` is copied byte by byte into `a` +// implement your solution +// +// commit your answers (bare3_4) +// +// 5. look for a way to make this copy done without a loop +// implement your solution +// +// commit your answers (bare3_5) + // As we are not using interrupts, we just register a dummy catch all handler #[link_section = ".vector_table.interrupts"] #[used] diff --git a/examples/bare4.rs b/examples/bare4.rs index 0dd033ee0ef6e99f87e734ee81b08faaf3abed1a..6fc12521306057ceed2e3c47854d2d523fc553fb 100644 --- a/examples/bare4.rs +++ b/examples/bare4.rs @@ -28,6 +28,7 @@ use address::*; #[inline(always)] fn read_u32(addr: u32) -> u32 { unsafe { core::ptr::read_volatile(addr as *const _) } + //core::ptr::read_volatile(addr as *const _) } #[inline(always)] @@ -44,11 +45,11 @@ fn wait(i: u32) { } fn main() { - // power on GPIOA, RM0368 6.3.11 + // power on GPIOA let r = read_u32(RCC_AHB1ENR); // read write_u32(RCC_AHB1ENR, r | 1); // set enable - // configure PA5 as output, RM0368 8.4.1 + // configure PA5 as output let r = read_u32(GPIOA_MODER) & !(0b11 << (5 * 2)); // read and mask write_u32(GPIOA_MODER, r | 0b01 << (5 * 2)); // set output mode @@ -56,16 +57,59 @@ fn main() { // this is more efficient as the read register is not needed. loop { - // set PA5 high, RM0368 8.4.7 + // set PA5 high write_u32(GPIOA_BSRR, 1 << 5); // set bit, output hight (turn on led) wait(10_000); - // set PA5 low, RM0368 8.4.7 + // set PA5 low write_u32(GPIOA_BSRR, 1 << (5 + 16)); // clear bit, output low (turn off led) wait(10_000); } } +// 1. build and run the application (debug build) +// did you enjoy the blinking? +// ** your answer here ** +// +// now lookup the data-sheets, and read each section referred, +// 6.3.11, 8.4.1, 8.4.7 +// +// document each low level access *code* by the appropriate section in the +// data sheet +// +// commit your answers (bare4_1) +// +// 2. comment out line 30 and uncomment line 31 (essentially omitting the `unsafe`) +// what was the error message and explain why, +// ** your answer here ** +// +// digging a bit deeper, why do you think `read_volatile` is declared `unsafe` +// (https://doc.rust-lang.org/core/ptr/fn.read_volatile.html, for some food for thought ) +// ** your answer here ** +// +// commit your answers (bare4_2) +// +// 3. +// volatile read/writes are explicit *volatile operations* in Rust, while in C they +// are declared at type level (i.e., access to varibles declared volatile amounts to +// volatile reads/and writes) +// +// both C and Rust (even more) allows code optimization to re-order operations, as long +// as data dependencies are preserved. +// +// why is important that ordering of volatile operations are ensured by the compiler? +// ** your answer here ** +// +// give an example in the above code, where reordering might make things go horribly wrong +// (hint, accessing a peripheral not being powered...) +// ** your answer here ** +// +// without the non-reording proprety of `write_volatile/read_volatile` could that happen in theory +// (argue from the point of data dependencies) +// ** your answer here ** +// +// commit your answers (bare4_3) + // As we are not using interrupts, we just register a dummy catch all handler #[link_section = ".vector_table.interrupts"] #[used] diff --git a/examples/bare5.rs b/examples/bare5.rs index 1e253e25b1ee80b513033cde583b98e178186078..8d5b12289f0f3d46886ab5822808c360f9b7e5e3 100644 --- a/examples/bare5.rs +++ b/examples/bare5.rs @@ -119,35 +119,62 @@ fn wait(i: u32) { } } +// system startup, can be hidden from the user fn main() { - // power on GPIOA, RM0368 6.3.11 - let rcc = RCC::get(); // get the reference to RCC in memory - unsafe { - let r = (*rcc).AHB1ENR.read(); // read - (*rcc).AHB1ENR.write(r | 1 << (0)); // set enable - } + let rcc = unsafe { &mut *RCC::get() }; // get the reference to RCC in memory + let gpioa = unsafe { &mut *GPIOA::get() }; // get the reference to GPIOA in memory + idle(rcc, gpioa); +} - // configure PA5 as output, RM0368 8.4.1 - let gpioa = GPIOA::get(); // get the reference to GPIOA in memory - unsafe { - let r = (*gpioa).MODER.read() & !(0b11 << (5 * 2)); // read and mask - (*gpioa).MODER.write(r | 0b01 << (5 * 2)); // set output mode +// user application +fn idle(rcc: &mut RCC, gpioa: &mut GPIOA) { + let rcc_copy = &rcc; + // power on GPIOA + let r = rcc.AHB1ENR.read(); // read + rcc.AHB1ENR.write(r | 1 << (0)); // set enable - // and alter the data output through the BSRR register - // this is more efficient as the read register is not needed. + // configure PA5 as output + let r = gpioa.MODER.read() & !(0b11 << (5 * 2)); // read and mask + gpioa.MODER.write(r | 0b01 << (5 * 2)); // set output mode - loop { - // set PA5 high, RM0368 8.4.7 - (*gpioa).BSRRH.write(1 << 5); // set bit, output hight (turn on led) - wait(10_000); + // and alter the data output through the BSRR register + // this is more efficient as the read register is not needed. - // set PA5 low, RM0368 8.4.7 - (*gpioa).BSRRL.write(1 << 5); // clear bit, output low (turn off led) - wait(10_000); - } + loop { + // set PA5 high + gpioa.BSRRH.write(1 << 5); // set bit, output hight (turn on led) + wait(10_000); + + // set PA5 low + gpioa.BSRRL.write(1 << 5); // clear bit, output low (turn off led) + wait(10_000); } } +// 1. C like API +// In C the .h files are used for defining interfaces, like function signatures (prototypes), +// structs and macros (but usually not the functions themselves) +// here is a peripheral abstraction quite similar to what you would find in the .h files +// provided by ST (and other companies). Actually, the file presesnted here is mostly a +// cut/paste/replace of the stm32f40x.h, just Rustified. +// +// I this case we pass mutable pointer to the `idle`. +// +// Rewrite the accesses in the loop to use the data registerf directly (and make a read/modify/write). +// +// Run and see that the program behaves the same. +// +// commit your answers (bare5_1) +// +// 2. +// Extend the read/write API with a modify, taking the address, field offsbet, field width, and value. +// +// Change the code into using your new API. +// +// Run and see that the program behaves the same. +// +// commit your answers (bare5_2) + // As we are not using interrupts, we just register a dummy catch all handler #[link_section = ".vector_table.interrupts"] #[used] diff --git a/examples/bare6.rs b/examples/bare6.rs index 493b814787224ae0d6cc27937fdf71ee22dcb496..d8553401c61a9c14677578e887f55d825d85bbdd 100644 --- a/examples/bare6.rs +++ b/examples/bare6.rs @@ -5,39 +5,49 @@ #![feature(use_nested_groups)] #![no_std] -extern crate cortex_m; -extern crate cortex_m_rt; +extern crate stm32f40x; #[macro_use] extern crate cortex_m_debug; -use cortex_m::{asm::bkpt, peripheral::DWT}; +use stm32f40x::{DWT, GPIOA, RCC}; + +fn main() { + ipln!("init"); + let dwt = unsafe { &mut *DWT.get() }; // get the reference to DWD in memory + let rcc = unsafe { &mut *RCC.get() }; // get the reference to RCC in memory + let gpioa = unsafe { &mut *GPIOA.get() }; // get the reference to GPIOA in memory + + dwt.enable_cycle_counter(); + idle(dwt, rcc, gpioa); +} // uses the DWT.CYCNT // doc: ARM trm_100166_0001_00_en.pdf, chapter 9.2 // we use the `cortex-m` abstraction -fn wait_cycles(nr_cycles: u32) { - unsafe { - let t = (*DWT.get()).cyccnt.read().wrapping_add(nr_cycles); - while ((*DWT.get()).cyccnt.read().wrapping_sub(t) as i32) < 0 {} - } +fn wait_cycles(dwt: &mut DWT, nr_cycles: u32) { + let t = dwt.cyccnt.read().wrapping_add(nr_cycles); + while (dwt.cyccnt.read().wrapping_sub(t) as i32) < 0 {} } -fn main() { - unsafe { (*DWT.get()).enable_cycle_counter() }; - let mut i = 0; - loop { - ipln!("tick {}", i); - wait_cycles(64_000_000); - i += 1; // this will eventually cause a panic, when the counter wraps. - } -} +// user application +fn idle(dwt: &mut DWT, rcc: &mut RCC, gpioa: &mut GPIOA) { + ipln!("idle"); + // power on GPIOA, RM0368 6.3.11 + rcc.ahb1enr.modify(|_, w| w.gpioaen().set_bit()); -// As we are not using interrupts, we just register a dummy catch all handler -#[link_section = ".vector_table.interrupts"] -#[used] -static INTERRUPTS: [extern "C" fn(); 240] = [default_handler; 240]; + // configure PA5 as output, RM0368 8.4.1 + gpioa.moder.modify(|_, w| w.moder5().bits(1)); -extern "C" fn default_handler() { - cortex_m::asm::bkpt(); + loop { + ipln!("led on"); + // set PA5 high, RM0368 8.4.7 + gpioa.bsrr.write(|w| w.bs5().set_bit()); + wait_cycles(dwt, 10_000); + + ipln!("idle off"); + // set PA5 low, RM0368 8.4.7 + gpioa.bsrr.write(|w| w.br5().set_bit()); + wait_cycles(dwt, 10_000); + } } diff --git a/rtfm-app Debug OpenOcd.launch b/rtfm-app Debug OpenOcd.launch deleted file mode 100644 index 100d56bde7e2bdc77d08a0d6cc15958964674216..0000000000000000000000000000000000000000 --- a/rtfm-app Debug OpenOcd.launch +++ /dev/null @@ -1,52 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" standalone="no"?> -<launchConfiguration type="com.atollic.hardwaredebug.launch.launchConfigurationType"> -<stringAttribute key="com.atollic.hardwaredebug.jlink_common.cpu_core" value="Cortex-M"/> -<stringAttribute key="com.atollic.hardwaredebug.jlink_common.device" value="STM32F401RE"/> -<stringAttribute key="com.atollic.hardwaredebug.jlink_common.endian" value="little"/> -<stringAttribute key="com.atollic.hardwaredebug.jlink_common.init_speed" value="4000"/> -<booleanAttribute key="com.atollic.hardwaredebug.jlink_common.jlink_check_serial_number" value="false"/> -<stringAttribute key="com.atollic.hardwaredebug.jlink_common.jlink_script_path" value=""/> -<booleanAttribute key="com.atollic.hardwaredebug.jlink_common.jlink_script_used" value="false"/> -<stringAttribute key="com.atollic.hardwaredebug.jlink_common.jlink_trace_port_cfg_path" value="/opt/truestudio/ide/plugins/com.atollic.truestudio.tsp.stm32_1.0.0.20171023-2304/tsp/etm/stm32f4xx.init"/> -<stringAttribute key="com.atollic.hardwaredebug.jlink_common.jlink_txt_serial_number" value=""/> -<booleanAttribute key="com.atollic.hardwaredebug.jlink_common.scan_chain_auto" value="true"/> -<intAttribute key="com.atollic.hardwaredebug.jlink_common.scan_chain_irpre" value="0"/> -<intAttribute key="com.atollic.hardwaredebug.jlink_common.scan_chain_pos" value="0"/> -<stringAttribute key="com.atollic.hardwaredebug.jlink_common.selected_rtos" value="No RTOS"/> -<intAttribute key="com.atollic.hardwaredebug.launch.formatVersion" value="2"/> -<stringAttribute key="com.atollic.hardwaredebug.launch.hwinitCommands" value="# Initialize your hardware here "/> -<stringAttribute key="com.atollic.hardwaredebug.launch.ipAddress" value="localhost"/> -<stringAttribute key="com.atollic.hardwaredebug.launch.jtagDevice" value="OpenOCD"/> -<intAttribute key="com.atollic.hardwaredebug.launch.portNumber" value="3333"/> -<stringAttribute key="com.atollic.hardwaredebug.launch.remoteCommand" value="target remote"/> -<stringAttribute key="com.atollic.hardwaredebug.launch.runCommands" value="# Load the program executable load # Set a breakpoint at main(). #tbreak main # Run to the breakpoint. continue"/> -<stringAttribute key="com.atollic.hardwaredebug.launch.serverParam" value="-f interface/stlink.cfg -f target/stm32f4x.cfg"/> -<booleanAttribute key="com.atollic.hardwaredebug.launch.startServer" value="true"/> -<booleanAttribute key="com.atollic.hardwaredebug.launch.swd_mode" value="false"/> -<stringAttribute key="com.atollic.hardwaredebug.launch.swv_port" value="2332"/> -<stringAttribute key="com.atollic.hardwaredebug.launch.swv_trace_div" value="0"/> -<stringAttribute key="com.atollic.hardwaredebug.launch.swv_trace_hclk" value="16000000"/> -<intAttribute key="com.atollic.hardwaredebug.launch.trace_system" value="0"/> -<booleanAttribute key="com.atollic.hardwaredebug.launch.useRemoteTarget" value="true"/> -<stringAttribute key="com.atollic.hardwaredebug.openocd.server_target" value="remote"/> -<stringAttribute key="org.eclipse.cdt.dsf.gdb.DEBUG_NAME" value="${TOOLCHAIN_PATH}/arm-atollic-eabi-gdb"/> -<booleanAttribute key="org.eclipse.cdt.dsf.gdb.UPDATE_THREADLIST_ON_SUSPEND" value="false"/> -<intAttribute key="org.eclipse.cdt.launch.ATTR_BUILD_BEFORE_LAUNCH_ATTR" value="2"/> -<stringAttribute key="org.eclipse.cdt.launch.COREFILE_PATH" value=""/> -<stringAttribute key="org.eclipse.cdt.launch.DEBUGGER_REGISTER_GROUPS" value=""/> -<stringAttribute key="org.eclipse.cdt.launch.PROGRAM_NAME" value="/home/pln/Atollic/TrueSTUDIO/ARM_workspace_8.1/rtfm-app/target/thumbv7em-none-eabihf/debug/examples/bare0.elf"/> -<stringAttribute key="org.eclipse.cdt.launch.PROJECT_ATTR" value="rtfm-app"/> -<booleanAttribute key="org.eclipse.cdt.launch.PROJECT_BUILD_CONFIG_AUTO_ATTR" value="false"/> -<stringAttribute key="org.eclipse.cdt.launch.PROJECT_BUILD_CONFIG_ID_ATTR" value=""/> -<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS"> -<listEntry value="/rtfm-app"/> -</listAttribute> -<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES"> -<listEntry value="4"/> -</listAttribute> -<listAttribute key="org.eclipse.debug.ui.favoriteGroups"> -<listEntry value="org.eclipse.debug.ui.launchGroup.debug"/> -</listAttribute> -<stringAttribute key="org.eclipse.dsf.launch.MEMORY_BLOCKS" value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <memoryBlockExpressionList context="reserved-for-future-use"/> "/> -<stringAttribute key="process_factory_id" value="org.eclipse.cdt.dsf.gdb.GdbProcessFactory"/> -</launchConfiguration>