Skip to content
This repository was archived by the owner on Jul 6, 2019. It is now read-only.

Commit c3e54e6

Browse files
committed
build: Generate layout.ld from templates
1 parent 4441930 commit c3e54e6

19 files changed

+235
-126
lines changed

Cargo.toml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,3 +46,9 @@ path = "./macro_platformtree"
4646

4747
[dev-dependencies.macro_zinc]
4848
path = "./macro_zinc"
49+
50+
[build-dependencies]
51+
rustache = "0.1"
52+
serde = "= 0.8.8"
53+
serde_derive = "= 0.8.8"
54+
serde_yaml = "0.4.1"

build.rs

Lines changed: 122 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,15 @@
1+
#![feature(custom_attribute, proc_macro, rustc_macro)]
2+
3+
extern crate rustache;
4+
#[macro_use]
5+
extern crate serde_derive;
6+
extern crate serde_yaml;
7+
18
use std::ascii::AsciiExt;
29
use std::env;
310
use std::fs;
411
use std::io;
5-
use std::path::Path;
12+
use std::path::{Path, PathBuf};
613

714
fn get_platform() -> Option<String> {
815
let features = env::vars().filter(|&(ref key, _)| key.starts_with("CARGO_FEATURE_MCU_"));
@@ -14,29 +21,125 @@ fn get_platform() -> Option<String> {
1421
}
1522
}
1623

17-
fn file_exists(file: &Path) -> bool {
24+
fn file_exists<P: AsRef<Path>>(file: P) -> bool {
25+
let file: &Path = file.as_ref();
1826
match fs::metadata(file) {
1927
Ok(_) => true,
2028
// Check for ENOENT (No such file or directory)
2129
Err(e) => e.raw_os_error() != Some(2),
2230
}
2331
}
2432

33+
#[derive(Debug)]
34+
enum GenerateLayoutError {
35+
Io(io::Error),
36+
Yaml(serde_yaml::Error),
37+
Rustache(rustache::RustacheError),
38+
}
39+
40+
fn target_dir<P: AsRef<Path>>(target: P) -> PathBuf {
41+
Path::new("src/hal").join(target)
42+
}
43+
44+
trait RustacheHash {
45+
fn rustache_insert<'a>(&self, hb: rustache::HashBuilder<'a>) -> rustache::HashBuilder<'a>;
46+
}
47+
48+
#[derive(Serialize, Deserialize, Debug)]
49+
struct McuLayout {
50+
vectors: String,
51+
memories: Vec<McuMemory>,
52+
}
53+
54+
impl RustacheHash for McuLayout {
55+
fn rustache_insert<'a>(&self, hb: rustache::HashBuilder<'a>) -> rustache::HashBuilder<'a> {
56+
let memories = self.memories.iter().fold(rustache::VecBuilder::new(), |memories, memory| {
57+
memories.push(memory.rustache_insert(rustache::HashBuilder::new()))
58+
});
59+
hb
60+
.insert("vectors", self.vectors.clone())
61+
.insert("memories", memories)
62+
}
63+
}
64+
65+
#[derive(Serialize, Deserialize, Debug)]
66+
struct McuMemory {
67+
name: String,
68+
mode: String,
69+
origin: u64,
70+
length: u64,
71+
}
72+
73+
impl RustacheHash for McuMemory {
74+
fn rustache_insert<'a>(&self, hb: rustache::HashBuilder<'a>) -> rustache::HashBuilder<'a> {
75+
hb
76+
.insert("name", self.name.clone())
77+
.insert("mode", self.mode.clone())
78+
.insert("origin", self.origin as i32)
79+
.insert("length", self.length as i32)
80+
}
81+
}
82+
83+
fn generate_layout<P: AsRef<Path>>(target: &str, out_path: P) -> Result<(), GenerateLayoutError> {
84+
use rustache::Render;
85+
use std::io::Read;
86+
87+
let layout_file = target_dir(target).join("layout.yml");
88+
fs::File::open(layout_file)
89+
.map_err(|e| GenerateLayoutError::Io(e))
90+
.and_then(|f| {
91+
let res: serde_yaml::Result<McuLayout> = serde_yaml::from_reader(f);
92+
res.map_err(|e| GenerateLayoutError::Yaml(e))
93+
})
94+
.and_then(|layout| {
95+
fs::File::open("src/hal/layout.ld.in")
96+
.and_then(|mut f| {
97+
let mut buf = String::from("");
98+
f.read_to_string(&mut buf)
99+
.map(|_| (layout, buf))
100+
})
101+
.map_err(|e| GenerateLayoutError::Io(e))
102+
})
103+
.and_then(|(layout, template)| {
104+
fs::OpenOptions::new().write(true).create_new(true).open(out_path)
105+
.map_err(|e| GenerateLayoutError::Io(e))
106+
.map(|f| (layout, template, f))
107+
})
108+
.and_then(|(layout, template, mut f)| {
109+
let layout = &layout;
110+
let hb = rustache::HashBuilder::new();
111+
let hb = layout.rustache_insert(hb);
112+
hb.render(&template, &mut f)
113+
.map_err(|e| GenerateLayoutError::Rustache(e))
114+
})
115+
}
116+
25117
fn copy_linker_scripts<P: AsRef<Path>, Q: AsRef<Path>>(target: P, out_path: Q) -> io::Result<()> {
26118
let path_prefix = if env::var("CARGO_MANIFEST_DIR").unwrap().find("/examples/").is_none() {
27119
Path::new(".")
28120
} else {
29121
Path::new("./../..")
30122
};
31123
// Try copying the linker scripts
32-
let target_dir = Path::new("src/hal").join(target);
124+
let target_dir = target_dir(target);
33125
let out_dir: &Path = out_path.as_ref();
34126
try!(fs::copy(path_prefix.join("src/hal/layout_common.ld"), out_dir.join("layout_common.ld")));
35127
let iomem_ld = path_prefix.join(target_dir.join("iomem.ld"));
36128
if file_exists(iomem_ld.as_path()) {
37129
try!(fs::copy(iomem_ld, out_dir.join("iomem.ld")));
130+
} else {
131+
try!(fs::OpenOptions::new().create(true).write(true).open(out_dir.join("iomem.ld")));
132+
}
133+
// If the MCU has a layout.ld script, we want to override the generated one
134+
// with new one.
135+
let layout_ld = path_prefix.join(target_dir.join("layout.ld"));
136+
if file_exists(layout_ld.as_path()) {
137+
let layout_ld_out = out_dir.join("layout.ld");
138+
if file_exists(&layout_ld_out) {
139+
try!(fs::remove_file(&layout_ld_out))
140+
}
141+
try!(fs::copy(layout_ld, &layout_ld_out));
38142
}
39-
try!(fs::copy(path_prefix.join(target_dir.join("layout.ld")), out_dir.join("layout.ld")));
40143

41144
Ok(())
42145
}
@@ -48,9 +151,24 @@ fn main() {
48151
return;
49152
},
50153
};
154+
51155
// Get output directory for cargo for zinc crate
52156
let out_dir = env::var("OUT_DIR").unwrap();
53157

158+
let layout_path = Path::new(&out_dir).join("layout.ld");
159+
if file_exists(&layout_path) {
160+
match fs::remove_file(&layout_path) {
161+
Ok(..) => {},
162+
Err(e) => panic!("Failed to clean layout.ld: {}", e),
163+
}
164+
}
165+
166+
// Create the new layout.ld
167+
match generate_layout(platform.as_str(), &layout_path) {
168+
Ok(..) => {},
169+
Err(e) => panic!("Failed to create layout.ld: {:?}", e),
170+
}
171+
54172
// Move linker scripts to cargo output dir
55173
match copy_linker_scripts(&platform, &out_dir) {
56174
Ok(_) => {},

src/hal/k20/layout.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
---
2+
vectors: rom
3+
memories: []

src/hal/layout.ld.in

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
INCLUDE iomem.ld
2+
3+
_data_load = LOADADDR(.data);
4+
5+
ENTRY(main)
6+
7+
MEMORY
8+
{
9+
{{#memories}}
10+
{{name}}({{mode}}) : ORIGIN = {{origin}}, LENGTH = {{length}}
11+
{{/memories}}
12+
}
13+
14+
__STACK_BASE = ORIGIN(ram) + LENGTH(ram);
15+
16+
REGION_ALIAS("vectors", {{vectors}});
17+
18+
INCLUDE layout_common.ld

src/hal/lpc11xx/layout.ld

Lines changed: 0 additions & 15 deletions
This file was deleted.

src/hal/lpc11xx/layout.yml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
---
2+
vectors: rom
3+
memories:
4+
- name: rom
5+
mode: RX
6+
origin: 0x00000000
7+
length: 0x8000
8+
- name: ram
9+
mode: WAIL
10+
origin: 0x10000000
11+
length: 0x1000

src/hal/lpc17xx/iomem.ld

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,3 +89,5 @@ lpc17xx_iomem_PCLKSEL0 = 0x400FC1A8;
8989
lpc17xx_iomem_PCLKSEL1 = 0x400FC1AC;
9090

9191
lpc17xx_iomem_SCS = 0x400FC1A0;
92+
93+
isr_reserved_1 = 0 - (__STACK_BASE + main + 1 + isr_nmi + 1 + isr_hardfault + 1);

src/hal/lpc17xx/layout.ld

Lines changed: 0 additions & 19 deletions
This file was deleted.

src/hal/lpc17xx/layout.yml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
---
2+
vectors: rom
3+
memories:
4+
- name: rom
5+
mode: RX
6+
origin: 0x00000000
7+
length: 0x10000
8+
- name: ram
9+
mode: WAIL
10+
origin: 0x10000000
11+
length: 0x2000

src/hal/stm32f1/layout.ld

Lines changed: 0 additions & 16 deletions
This file was deleted.

src/hal/stm32f1/layout.yml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
---
2+
vectors: rom
3+
memories:
4+
- name: rom
5+
mode: RX
6+
origin: 0x08000000
7+
length: 0x10000
8+
- name: ram
9+
mode: WAIL
10+
origin: 0x20000000
11+
length: 0x4FFF

src/hal/stm32f4/layout.ld

Lines changed: 0 additions & 18 deletions
This file was deleted.

src/hal/stm32f4/layout.yml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
---
2+
vectors: rom
3+
memories:
4+
- name: rom
5+
mode: RX
6+
origin: 0x08000000
7+
length: 0x100000
8+
- name: ram_c
9+
mode: WAIL
10+
origin: 0x10000000
11+
length: 0x10000
12+
- name: ram
13+
mode: WAIL
14+
origin: 0x20000000
15+
length: 0x20000

src/hal/stm32f7/layout.ld

Lines changed: 0 additions & 22 deletions
This file was deleted.

src/hal/stm32f7/layout.yml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
---
2+
vectors: rom
3+
memories:
4+
- name: rom
5+
mode: RX
6+
origin: 0x08000000
7+
length: 0x100000
8+
- name: ram_c
9+
mode: WAIL
10+
origin: 0x10000000
11+
length: 0x10000
12+
- name: ram
13+
mode: WAIL
14+
origin: 0x20000000
15+
length: 0x50000

src/hal/stm32l1/layout.ld

Lines changed: 0 additions & 16 deletions
This file was deleted.

0 commit comments

Comments
 (0)