aboutsummaryrefslogtreecommitdiff
path: root/scripts
diff options
context:
space:
mode:
authorchrysn2012-10-29 14:34:42 +0100
committerchrysn2012-10-29 14:34:42 +0100
commita01e5c201bca79b9dc4fe4363d843f8c7dad5290 (patch)
tree557308df3df94393c51164d7bfb193787877878c /scripts
parente55a9e387560924a157d60b29a3aa49300b9b456 (diff)
parentf594af86c8515889565bbc17d13e16d8f56eea9f (diff)
Merge branch 'generalizations'
this merges common c and header files of different architectures, adds a dispatch mechanism and yaml descriptions of interrupt handlers from which the whole interrupt table setup c code is generated.
Diffstat (limited to 'scripts')
-rwxr-xr-xscripts/irq2nvic_h160
1 files changed, 160 insertions, 0 deletions
diff --git a/scripts/irq2nvic_h b/scripts/irq2nvic_h
new file mode 100755
index 0000000..23e365d
--- /dev/null
+++ b/scripts/irq2nvic_h
@@ -0,0 +1,160 @@
+#!/usr/bin/env python
+
+# This file is part of the libopencm3 project.
+#
+# Copyright (C) 2012 chrysn <chrysn@fsfe.org>
+#
+# This library is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with this library. If not, see <http://www.gnu.org/licenses/>.
+
+"""Generate an nvic.h header from a small YAML file describing the interrupt
+numbers.
+
+Code generation is chosen here because the resulting C code needs to be very
+repetetive (definition of the IRQ numbers, function prototypes, weak fallback
+definition and vector table definition), all being very repetitive. No portable
+method to achive the same thing with C preprocessor is known to the author.
+(Neither is any non-portable method, for that matter.)"""
+
+import sys
+import os
+import os.path
+import yaml
+
+template_nvic_h = '''\
+/* This file is part of the libopencm3 project.
+ *
+ * It was generated by the irq2nvic_h script.
+ */
+
+#ifndef {includeguard}
+#define {includeguard}
+
+#include <libopencm3/cm3/nvic.h>
+
+/** @defgroup CM3_nvic_defines_{partname_doxygen} User interrupts for {partname_humanreadable}
+ @ingroup CM3_nvic_defines
+
+ @{{*/
+
+{irqdefinitions}
+
+#define NVIC_IRQ_COUNT {irqcount}
+
+/**@}}*/
+
+#define WEAK __attribute__ ((weak))
+
+/** @defgroup CM3_nvic_isrprototypes_{partname_doxygen} User interrupt service routines (ISR) prototypes for {partname_humanreadable}
+ @ingroup CM3_nvic_isrprototypes
+
+ @{{*/
+
+BEGIN_DECLS
+
+{isrprototypes}
+
+END_DECLS
+
+/**@}}*/
+
+#endif /* {includeguard} */
+'''
+
+template_vector_nvic_c = '''\
+/* This file is part of the libopencm3 project.
+ *
+ * It was generated by the irq2nvic_h script.
+ *
+ * This part needs to get included in the compilation unit where
+ * blocking_handler gets defined due to the way #pragma works.
+ */
+
+
+/** @defgroup CM3_nvic_isrpragmas_{partname_doxygen} User interrupt service routines (ISR) defaults for {partname_humanreadable}
+ @ingroup CM3_nvic_isrpragmas
+
+ @{{*/
+
+{isrpragmas}
+
+/**@}}*/
+
+/* Initialization template for the interrupt vector table. This definition is
+ * used by the startup code generator (vector.c) to set the initial values for
+ * the interrupt handling routines to the chip family specific _isr weak
+ * symbols. */
+
+#define IRQ_HANDLERS \\
+ {vectortableinitialization}
+'''
+
+def convert(infile, outfile_nvic, outfile_vectornvic):
+ data = yaml.load(infile)
+
+ irq2name = list(enumerate(data['irqs']) if isinstance(data['irqs'], list) else data['irqs'].items())
+ irqnames = [v for (k,v) in irq2name]
+
+ if isinstance(data['irqs'], list):
+ data['irqcount'] = len(irq2name)
+ else:
+ data['irqcount'] = max(data['irqs'].keys()) + 1
+
+ data['irqdefinitions'] = "\n".join('#define NVIC_%s_IRQ %d'%(v.upper(),k) for (k,v) in irq2name)
+ data['isrprototypes'] = "\n".join('void WEAK %s_isr(void);'%name.lower() for name in irqnames)
+ data['isrpragmas'] = "\n".join('#pragma weak %s_isr = blocking_handler'%name.lower() for name in irqnames)
+ data['vectortableinitialization'] = ', \\\n '.join('[NVIC_%s_IRQ] = %s_isr'%(name.upper(), name.lower()) for name in irqnames)
+
+ outfile_nvic.write(template_nvic_h.format(**data))
+ outfile_vectornvic.write(template_vector_nvic_c.format(**data))
+
+def makeparentdir(filename):
+ try:
+ os.makedirs(os.path.dirname(filename))
+ except OSError:
+ # where is my 'mkdir -p'?
+ pass
+
+def needs_update(infiles, outfiles):
+ timestamp = lambda filename: os.stat(filename).st_mtime
+ return any(not os.path.exists(o) for o in outfiles) or max(map(timestamp, infiles)) > min(map(timestamp, outfiles))
+
+def main():
+ if sys.argv[1] == '--remove':
+ remove = True
+ del sys.argv[1]
+ else:
+ remove = False
+ infile = sys.argv[1]
+ if not infile.startswith('./include/libopencm3/') or not infile.endswith('/irq.yaml'):
+ raise ValueError("Arguent must match ./include/libopencm3/**/irq.yaml")
+ nvic_h = infile.replace('irq.yaml', 'nvic.h')
+ vector_nvic_c = infile.replace('./include/libopencm3/', './lib/').replace('irq.yaml', 'vector_nvic.c')
+
+ if remove:
+ if os.path.exists(nvic_h):
+ os.unlink(nvic_h)
+ if os.path.exists(vector_nvic_c):
+ os.unlink(vector_nvic_c)
+ sys.exit(0)
+
+ if not needs_update([__file__, infile], [nvic_h, vector_nvic_c]):
+ sys.exit(0)
+
+ makeparentdir(nvic_h)
+ makeparentdir(vector_nvic_c)
+
+ convert(open(infile), open(nvic_h, 'w'), open(vector_nvic_c, 'w'))
+
+if __name__ == "__main__":
+ main()