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

Generate layout.ld from templates + data #408

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,9 @@ path = "./macro_platformtree"

[dev-dependencies.macro_zinc]
path = "./macro_zinc"

[build-dependencies]
rustache = "0.1"
serde = "= 0.8.8"
serde_derive = "= 0.8.8"
serde_yaml = "0.4.1"
136 changes: 127 additions & 9 deletions build.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
#![feature(custom_attribute, proc_macro, rustc_macro)]

extern crate rustache;
#[macro_use]
extern crate serde_derive;
extern crate serde_yaml;

use std::ascii::AsciiExt;
use std::env;
use std::fs;
use std::io;
use std::path::Path;
use std::path::{Path, PathBuf};

fn get_platform() -> Option<String> {
let features = env::vars().filter(|&(ref key, _)| key.starts_with("CARGO_FEATURE_MCU_"));
Expand All @@ -14,12 +21,97 @@ fn get_platform() -> Option<String> {
}
}

fn file_exists(file: &Path) -> bool {
match fs::metadata(file) {
Ok(_) => true,
// Check for ENOENT (No such file or directory)
Err(e) => e.raw_os_error() != Some(2),
}
fn file_exists<P: AsRef<Path>>(file: P) -> bool {
let file: &Path = file.as_ref();
match fs::metadata(file) {
Ok(_) => true,
// Check for ENOENT (No such file or directory)
Err(e) => e.raw_os_error() != Some(2),
}
}

#[derive(Debug)]
enum GenerateLayoutError {
Io(io::Error),
Yaml(serde_yaml::Error),
Rustache(rustache::RustacheError),
}

fn target_dir<P: AsRef<Path>>(target: P) -> PathBuf {
Path::new("src/hal").join(target)
}

trait RustacheHash {
fn rustache_insert<'a>(&self, hb: rustache::HashBuilder<'a>) -> rustache::HashBuilder<'a>;
}

#[derive(Serialize, Deserialize, Debug)]
struct McuLayout {
vectors: String,
memories: Vec<McuMemory>,
}

impl RustacheHash for McuLayout {
fn rustache_insert<'a>(&self, hb: rustache::HashBuilder<'a>) -> rustache::HashBuilder<'a> {
let memories = self.memories.iter().fold(rustache::VecBuilder::new(), |memories, memory| {
memories.push(memory.rustache_insert(rustache::HashBuilder::new()))
});
hb
.insert("vectors", self.vectors.clone())
.insert("memories", memories)
}
}

#[derive(Serialize, Deserialize, Debug)]
struct McuMemory {
name: String,
mode: String,
origin: u64,
length: u64,
}

impl RustacheHash for McuMemory {
fn rustache_insert<'a>(&self, hb: rustache::HashBuilder<'a>) -> rustache::HashBuilder<'a> {
hb
.insert("name", self.name.clone())
.insert("mode", self.mode.clone())
.insert("origin", self.origin as i32)
.insert("length", self.length as i32)
}
}

fn generate_layout<P: AsRef<Path>>(target: &str, out_path: P) -> Result<(), GenerateLayoutError> {
use rustache::Render;
use std::io::Read;

let layout_file = target_dir(target).join("layout.yml");
fs::File::open(layout_file)
.map_err(|e| GenerateLayoutError::Io(e))
.and_then(|f| {
let res: serde_yaml::Result<McuLayout> = serde_yaml::from_reader(f);
res.map_err(|e| GenerateLayoutError::Yaml(e))
})
.and_then(|layout| {
fs::File::open("src/hal/layout.ld.in")
.and_then(|mut f| {
let mut buf = String::from("");
f.read_to_string(&mut buf)
.map(|_| (layout, buf))
})
.map_err(|e| GenerateLayoutError::Io(e))
})
.and_then(|(layout, template)| {
fs::OpenOptions::new().write(true).create_new(true).open(out_path)
.map_err(|e| GenerateLayoutError::Io(e))
.map(|f| (layout, template, f))
})
.and_then(|(layout, template, mut f)| {
let layout = &layout;
let hb = rustache::HashBuilder::new();
let hb = layout.rustache_insert(hb);
hb.render(&template, &mut f)
.map_err(|e| GenerateLayoutError::Rustache(e))
})
}

fn copy_linker_scripts<P: AsRef<Path>, Q: AsRef<Path>>(target: P, out_path: Q) -> io::Result<()> {
Expand All @@ -29,14 +121,25 @@ fn copy_linker_scripts<P: AsRef<Path>, Q: AsRef<Path>>(target: P, out_path: Q) -
Path::new("./../..")
};
// Try copying the linker scripts
let target_dir = Path::new("src/hal").join(target);
let target_dir = target_dir(target);
let out_dir: &Path = out_path.as_ref();
try!(fs::copy(path_prefix.join("src/hal/layout_common.ld"), out_dir.join("layout_common.ld")));
let iomem_ld = path_prefix.join(target_dir.join("iomem.ld"));
if file_exists(iomem_ld.as_path()) {
try!(fs::copy(iomem_ld, out_dir.join("iomem.ld")));
} else {
try!(fs::OpenOptions::new().create(true).write(true).open(out_dir.join("iomem.ld")));
}
// If the MCU has a layout.ld script, we want to override the generated one
// with new one.
let layout_ld = path_prefix.join(target_dir.join("layout.ld"));
if file_exists(layout_ld.as_path()) {
let layout_ld_out = out_dir.join("layout.ld");
if file_exists(&layout_ld_out) {
try!(fs::remove_file(&layout_ld_out))
}
try!(fs::copy(layout_ld, &layout_ld_out));
}
try!(fs::copy(path_prefix.join(target_dir.join("layout.ld")), out_dir.join("layout.ld")));

Ok(())
}
Expand All @@ -48,9 +151,24 @@ fn main() {
return;
},
};

// Get output directory for cargo for zinc crate
let out_dir = env::var("OUT_DIR").unwrap();

let layout_path = Path::new(&out_dir).join("layout.ld");
if file_exists(&layout_path) {
match fs::remove_file(&layout_path) {
Ok(..) => {},
Err(e) => panic!("Failed to clean layout.ld: {}", e),
}
}

// Create the new layout.ld
match generate_layout(platform.as_str(), &layout_path) {
Ok(..) => {},
Err(e) => panic!("Failed to create layout.ld: {:?}", e),
}

// Move linker scripts to cargo output dir
match copy_linker_scripts(&platform, &out_dir) {
Ok(_) => {},
Expand Down
3 changes: 3 additions & 0 deletions src/hal/k20/layout.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
---
vectors: rom
memories: []
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This naming is slightly awkward. Why not memory_ranges?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed. Much better.

18 changes: 18 additions & 0 deletions src/hal/layout.ld.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
INCLUDE iomem.ld

_data_load = LOADADDR(.data);

ENTRY(main)

MEMORY
{
{{#memories}}
{{name}}({{mode}}) : ORIGIN = {{origin}}, LENGTH = {{length}}
{{/memories}}
}

__STACK_BASE = ORIGIN(ram) + LENGTH(ram);

REGION_ALIAS("vectors", {{vectors}});

INCLUDE layout_common.ld
15 changes: 0 additions & 15 deletions src/hal/lpc11xx/layout.ld

This file was deleted.

11 changes: 11 additions & 0 deletions src/hal/lpc11xx/layout.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
vectors: rom
memories:
- name: rom
mode: RX
origin: 0x00000000
length: 0x8000
- name: ram
mode: WAIL
origin: 0x10000000
length: 0x1000
2 changes: 2 additions & 0 deletions src/hal/lpc17xx/iomem.ld
Original file line number Diff line number Diff line change
Expand Up @@ -89,3 +89,5 @@ lpc17xx_iomem_PCLKSEL0 = 0x400FC1A8;
lpc17xx_iomem_PCLKSEL1 = 0x400FC1AC;

lpc17xx_iomem_SCS = 0x400FC1A0;

isr_reserved_1 = 0 - (__STACK_BASE + main + 1 + isr_nmi + 1 + isr_hardfault + 1);
19 changes: 0 additions & 19 deletions src/hal/lpc17xx/layout.ld

This file was deleted.

11 changes: 11 additions & 0 deletions src/hal/lpc17xx/layout.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
vectors: rom
memories:
- name: rom
mode: RX
origin: 0x00000000
length: 0x10000
- name: ram
mode: WAIL
origin: 0x10000000
length: 0x2000
16 changes: 0 additions & 16 deletions src/hal/stm32f1/layout.ld

This file was deleted.

11 changes: 11 additions & 0 deletions src/hal/stm32f1/layout.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
vectors: rom
memories:
- name: rom
mode: RX
origin: 0x08000000
length: 0x10000
- name: ram
mode: WAIL
origin: 0x20000000
length: 0x4FFF
18 changes: 0 additions & 18 deletions src/hal/stm32f4/layout.ld

This file was deleted.

15 changes: 15 additions & 0 deletions src/hal/stm32f4/layout.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
vectors: rom
memories:
- name: rom
mode: RX
origin: 0x08000000
length: 0x100000
- name: ram_c
mode: WAIL
origin: 0x10000000
length: 0x10000
- name: ram
mode: WAIL
origin: 0x20000000
length: 0x20000
22 changes: 0 additions & 22 deletions src/hal/stm32f7/layout.ld

This file was deleted.

15 changes: 15 additions & 0 deletions src/hal/stm32f7/layout.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
vectors: rom
memories:
- name: rom
mode: RX
origin: 0x08000000
length: 0x100000
- name: ram_c
mode: WAIL
origin: 0x10000000
length: 0x10000
- name: ram
mode: WAIL
origin: 0x20000000
length: 0x50000
16 changes: 0 additions & 16 deletions src/hal/stm32l1/layout.ld

This file was deleted.

Loading