9/19/2015 9:17PM
How to import APP
Manifest
How to require multiple apps
MF
Sharability
Resource Group
Signal and SignalConnection
Deveice Explorer
Signal Design
Advanced Widegets
Error Report
How to import APP
8/25/2015 4:19 PM
如何在DAVE4 SDK import已有的APP
1.在 -> Dave -> Model -> APPS 中找到app源文件 ALT+ENTER 找到文件地址。
2.找到Uimodel文件夹下的.ui文件 将它更名去除”_0” 例如:CLOCK_XMC1.ui
3.打开DAVE4 SDK 新建dave sdk project 命名为CLOCK_XMC1
4.把app源文件对应复制到新工程中
5.打开template,manifest 文件注释如图:
6.保存
返回顶部
Mainifest
8/25/2015 4:19 PM
什么是Manifest?
Manifest是用户对APP进行控制的文件。它可以和Widgets窗体部件互相交互,显示给用户,读写窗体上的数据,所以在恰当的逻辑下APP可以与寄存器交互申请必要的硬件资源和声明适当的信号。有对象用于准备生成代码,从manifest对象中获取数值和使用templates生成 .c 文件。
Manifest的结构由Manifest Structure决定,它主要是一个Groovy类,用户应该在构造函数中写APP的程序和generateFiles()方法。
为什么需要Manifest?
基本上manifest是APP 的核心,没有它你可以生成不错的app GUI但它不能生成任何代码,不能与GUI上的部件交互也不能申请硬件资源。
Manifest在哪里?
在DAVE Apps Explorer → → MANIFEST → .manifest
Manifest Properties
每一个DAVE™ APP 必须要有一个manifest文件。例如:DEMOAPP.manifest.
Manifest包含下面部分:
1. 加载声明(Import statements)
2. 类(Class object for DAVE™ APP (e.g. DEMOAPP))
所有的属性必须在app类中定义。如果它们没有被声明,在生成app时就会产生错误。
这些属性不能被app的GUI改变。它们能以任何顺序被定义,能在templates file 中被读取。
属性应该这样定义:
def <property_name> = <value>
<Type> <property_name> = <value>
在下面的程序你能看到默认生成的manifest file 和其中的定义和各个属性:
// Import statements
import ifx.davex.app.manifest.*
class DEMOAPP extends DEMOAPP_GUI {
// Note : Following APP properties are mandatory and important
// Begin : APP property section
/**
* APP version
* Format: a string with three digit separated by a dot.
*/
def version = '1.0.0'
/**
* APP categories declaration.
* It is list of strings. Subcategories are separated by slash.
* No limits on number of categories and subcategories depth.
*/
def categoriesDescription = ["Category/Sub Category"]
/**
* Minimum DAVE version required for this APP.
*
* It is string with three digit separated by a dot.
*/
def minDaveVersion = '4.0.0'
/**
* Keywords used by search feature in APPs selection view
*
* It is a list of string.
*/
def keywords = ['My keyword']
/**
* softwareIDs is used to declare which devices are compatible with this APP.
* It is a map with key a string containing a pattern that shall match the SW id of
* the device and as value the minimal version of the APP.
*/
// Any step of XMC4500F144 and XMC4400F144
// Any step of XMC4400F100 and XMC4400F64
// Any step, any variant and any packages of XMC1300
def softwareIDs = [
"XMC4.[4-5].00.F144.*":"1.0.0",
"XMC4.4.00.(F100|F64).*":"1.0.0",
"XMC1.3.*.*.*":"1.0.0"
]
/**
* Singleton property:
* When it is true the APP can be instantiated only once.
*/
def singleton = false
/**
* initProvider property
* It shall be true to add a call to _Init()
*/
def initProvider = false
/**
* Deprecated APP
* Set it to true to indicate that the APP shall be not used for new projects.
*/
def deprecated = false
/**
* Sharable property.
* It shall be true to allows multiple APPs to require the same instance of this APP.
*/
def sharable = false
/**
* APP function description.
*/
def description = "Here the APP description. Please add appropriate APP description"
// End : APP property section
// Begin : User APP property section
// End : User APP property section
// APP Constructor
public DEMOAPP(DaveEnv daveEnv) {
//TODO: Initialize manifest variables here
}
// File Generation
def generateFiles(){
generate("demoapp.tmpl", "demoapp.h", false)
}
}
**属性:**version
categoriesDescription
minDaveVersion
keywords
softwareIDs
singleton
initProvider
deprecated
sharable
descrition
返回顶部
##How to require multiple apps## **如何在父APP中建立多个APP
** 在这个demo APP中,我们需要2-5个DIGITAL_IO APP 根据微处理器的型号(XMC4500两个XMC1200五个)。最简单的方法是写下建立一个APP的语句复制2遍然后用if判断是不是1200来决定是否有接下来的3遍定义。
然而,我们可以用循环,Groovy来使它更为紧凑。
首先,我们以最大可能用的数目来定义”MRequiredApp”
// Begin : User APP property section
MRequiredApp appres_digital_io_0 /* DIGITAL_IO APP */
MRequiredApp appres_digital_io_1 /* DIGITAL_IO APP */
MRequiredApp appres_digital_io_2 /* DIGITAL_IO APP */
MRequiredApp appres_digital_io_3 /* DIGITAL_IO APP */
MRequiredApp appres_digital_io_4 /* DIGITAL_IO APP */
在类中我们将用前面的定义:
/* --------------------------------------------------------------- */
/* ------------ APP consumption Block ---------------------------- */
/* --------------------------------------------------------------- */
/* DIGITAL_IO APP from 2 to 5 instances */
for(int i = 0; i
##MF##
**声明:**
MF(
Closure function,
class returnType
)
**描述:**一个标准的APP需要一些从GUI上获取输入值的逻辑,用他们计算出另外的数值传递给template文件或者显示在GUI上另外的窗体部件上。
这可以通过MF函数来实现(事实上MF并不是一个函数而是一个闭包,例如一个构造函数的函数)。这种特殊的类型需要与Groovy的闭包区分。
Parameter name | Parameter type | Description |
function | function | A Closure means some embedded code between braces |
returnType | class | This parameter determines the class type of the closure (e.g. “Boolean”, “Integer”, “String”, “Float”, “List”, “Map”) |
Instance constructor
**例子:**
在这个例子里我们的“DEMOAPP”有两个窗体元素:一个GLabel和一个GCheck。GLabel的可见属性可以被MF设置和更新。在这种情况下当我们按下check box label 变得不可见。
void DEMOAPP(DaveEnv daveEnv){
glabel_1.visible = MF(
{ // The code between ..
gcheck_1.value // .. braces is known ..
}, // .. as the "Closure"
Boolean // This is the "class" return type
)
}
**MF 函数的执行方式:**在实际运行时DAVE™用一种特殊的方式来执行MF,与电子表格的执行方式相似。例如Microsoft Excel 文件。
我们把GUI中直接或间接变化的变量称为MVariables,就是MF中关联的变量。MVariables就像电子表中的单元格,他们可以包含常量或函数,常量就像一个没有输入值的函数。
**定义:**
**Free MVariable**: 包含常量的**MVariable** 或没有输入变量的MF 函数
**Non-free MVariable**: 有输入值的 **MF**函数
**MVariable 属性:**
1. 如果你读取Non-free MVariable你会得到函数值的更新。
2. 不可以更改”non-free” MVariable 的值或函数表达。
3. 如果你更改Free MVariable ,所有的于它相关的Non-free MVariable会由从属关系树向下递归直到所有受到影响的MVariables更新。
4. 不能做循环引用。
5. 所有APP GUI 变量是MVariables。
6. 如果更新变量相同MVariables将不会更新。
7. MVariables可以在APP 构建时设定,但在MF 函数中只可读,应为它会自动更新。
an example of MVariables dependency tree:
![](http://img-storage.qiniudn.com/15-8-25/93411753.jpg)
**MVariables 类型:**
每一个 GUI Widget 有多种变量属性,但在于GUI交互时只有MVariables 导出的属性可以被控制。
• MInt
• MFloat
• MString
• MBoolean
• MList
• MMap
返回顶部
## sharability ## DAVE™ APPs 根据manifest中的sharability 属性能被设置为可被共享或不可共享。Sharable的概念被用在当APP被需要在多个APP需要时。
如果一个APP可被共享:
1.多个APP可申请同一个已被共享的APP。
2.可被共享的APP自动成为non-free MVariables 所以它们的属性不能被“父”APP所更改。
3.可以通过“父”APP的manifest 设置RNOTSHARABLE参数把一个可被共享的APP可以转化成不可共享。
![](http://img-storage.qiniudn.com/15-8-27/206127.jpg)
如果一个APP不可被共享:
1.这个APP必定只有一个“父”APP。
2.APP属性是free MVariables,它们可以被“父”APP更改。
3.一个不可被共享的APP不可以转换成可共享的。
APP sharability property | Required as RSHARABLE | Required as RNOTSHARABLE |
def sharable = true | Sharable | Not Sharable |
def sharable = false | Not Sharable | Not Sharable |
返回顶部
## Resource Group ## 从单片机软件的角度,寄存器的位字段是最小的功能单元。HW resource group 是一系列能被URI(统一资源标识符)识别的位字段的集合。此外,这个寄存器位字段的实现的功能和组成的硬件功能块,E.g. CCU8中的一片CC8单元包含多个寄存器位字段,它相应的URI是”peripheral/ccu8/*/cc8/*”,”*”表示”any”单元或者slice。这一命名方法非常有用,它可以包含所有的硬件单元(与FPGA的概念相同)。
注意:尽管是同一个寄存器的位字段,也可能出现在不同的HW resource group中。
一个格式完整的硬件资源组是这样的:
http://www.infineon.com/0.1.30/peripheral/ccu8/0/cc8/0/gidls_ssi
写在manifest里:
resourceGroupUri=[“peripheral”,”ccu8”,”*”,”cc8”,”*”];
为了找到特定MCU的特定HW resource group 我们可以用DAVE™ SDK Device Explorer。
![](http://img-storage.qiniudn.com/15-8-27/56851413.jpg)
在这个例子里,HW resource group对应的是XMC4500-F144的”peripheral/ccu8/0/cc8/0”,你可以看到功能块CCU8的构成。
在manifest里我们能用一个或者多个resource group,定义虚拟信号,根据相应的应用需求给它们写名字。你可以不同APP中的信号之间建立连接,你也可以定义信号不连接,用户在Dave中连接。
从更为普通的观点来说,我们可以把硬件单元定义成包含io信号的一个或者多个resource groups,用这个resource groups可以实现一些特定的功能。
![](http://img-storage.qiniudn.com/15-8-27/93238524.jpg)
在硬件单元之间有很多相关的连接,因此人工地很难照顾到所有的连接。所以,solver会为我们解决这个问题,APP的开发者只需要定义resource groups之间的连接。例如:想象我们现在有4个资源组{ p1/0, p1/1, p2/0, p3/0 }(”P”代表”peripheral”(外设)),每一个硬件组包含一些resource groups(”rg”)
1. { rga/0, rga/1 } ⊂ p1/0
2. { rga/0, rga/1 } ⊂ p1/1
3. { rgb/0, rgb/1 } ⊂ p2/0
4. { rgz/0, rgz/1 } ⊂ p3/0
每一个成员代表了相应的硬件或resource group。在下面的情况中我们有两个相应的硬件组(“p1/0” and “p1/1”), 它们内部的resource group的名字是一样的,例如两个USIC模块分别有两个channel。
![](http://img-storage.qiniudn.com/15-8-27/59484063.jpg)
在你观察上图的过程中你可以发现有很多硬件的模块之间的连接(form interconnection network to interconnection work),但是没关系,我们有solver!通过solver的处理我们只需要关心资源组的连接,就如下图:
![](http://img-storage.qiniudn.com/15-8-27/89621344.jpg)
当solver决定是否需要连接被需要的resource group 之后,你可以通过在templetes或manifest 中要求solver返回相应的寄存器地址,或者你可以使用现有的APP让它们为你配置。
在最后,作为一个APP的开发者及使用者你只要关心虚拟的信号连接,不需要关心硬件连接了。
![](http://img-storage.qiniudn.com/15-8-27/48968590.jpg)
返回顶部
## Signal and SignalConnection ## 在DAVE™的代码引擎和DAVE™ SDK环境中,信号连接有着和电子上的意义不同的意义。对于“信号”这个概念,我们认为它是逻辑上的连接而不是像电平触发,边沿触发中断这样的物理信号。它们不是电气上的连接而是逻辑链接。
![](http://img-storage.qiniudn.com/15-8-27/64207880.jpg) 设想有三个信号{S1,S2,S3},S1,S2连在S3上,S1,S2可以影响到S3,但不可逆向。我们可以在帮助手册里发现这种信号之间的连接。例如下面的与门,或门。
你也可以发现被字段位影响的信号连接,如下图。
![](http://img-storage.qiniudn.com/15-8-27/50888169.jpg) 微处理器的不同构成要素用信号连接多路器和寄存器。 为了减少系统复杂度,使开发者高效工作。通过manifest来实现虚拟的信号连接时必要的。 这些信号称之为 “虚拟信号”因为我们不可能知道它们准确的通道直到solver给它们分配特定的硬件单元和资源组。
下图可以让你观察到CCU4和NVIC的硬件抽象原理图。在CCU4中有两个工作组(CC4 Slices)。每一个工作组包含三个信号(A,B,C),它们通过一个多路器和多路输出选择器和中断节点连接。为了选择多路器和多路输出选择器的信号,有专门的寄存器。
![](http://img-storage.qiniudn.com/15-8-27/33224579.jpg) 设想我们想要 连接CCU4上的信号A(其实我们不必关心哪一个)到中断节点D。 以前的做法是我们必须要在相应的寄存器上写入合适的数值去控制多路器。当只有一个硬件单元的年代几乎这不是什么问题,但如今的微处理器有着大量的外设和控制寄存器,因此对于一个开发者来说很难去关心所有的关于硬件模块,信号,寄存器等等的复杂连接可能性和同时考虑系统相容性。
因为上面的理由,我们开发了solver。与直接设定对应的资源组(eg.CCU4 slice0)不同,我们只需要选择声明“信号A”连接“信号D”就可以了,solver可以自动选择可被占用的资源。然后我们可以获取solver分配到的选择器的特定寄存器(SRS),把它用在template文件里用于生成代码来合理配置微处理器。
在这个例子中solver选择了CCU slice0,但在另一种配置中它可能选择slice1 ,谁知道呢! 我们限制硬件因为我们用了虚拟信号的概念。
![](http://img-storage.qiniudn.com/15-8-27/72164760.jpg) 为了向solver传递我们的需求,我们必须在manifest对资源,信号以及限制条件进行声明。 在例子中我们需要两个资源CC4和声明,申明两个虚拟信号A,D。我们可以给它们加连接的约束,亦可以让它们声明但不连接。因此用户可以在它们之间建立另一种连接(另选一个目标硬件,例如VADC)
为了申请资源你可以建立一个MVirtualResourceGroup对象,一个MVirtualSignal 来建立虚拟信号连接(‘M’来自于manifest类)。我们可以用方法addConnectionConstraint() 控制连接约束。
// Manifest code
// Begin : User APP property section
MVirtualResourceGroup cc4_slice // CC4 slice of CCU4
MVirtualResourceGroup interrupt_node // Interrupt node of NVIC
MVirtualSignal A // Example of source signal (e.g. pmus_omds)
MVirtualSignal D // Example of destination signal (e.g. signal_in)
// End : User APP property section
// APP Constructor
public TEST(DaveEnv daveEnv) {
cc4_slice = MVirtualResourceGroup("CC4 Slice", ["peripheral","ccu4","*","cc4","*"])
interrupt_node = MVirtualResourceGroup("INTERRUPT Node", ["peripheral","cpu","*","nvic","interrupt","*"])
A = MVirtualSignal(cc4_slice, "PMUS Service Request", "pmus_omds")
D = MVirtualSignal(interrupt_node, "Service Request Input", "signal_in")
addConnectionConstraint(A, D)
}
在这个简单的声明后,你可以在template文件里获取solver分配的值,再下面的例子中你能看到访问分配值得一种方法,生成的程序是不能编译的。
// Template code
for(def app : appInstancesList)
{
out.print("""
CCU4 hardware module == ${app.cc4_slice.getSolverUri()[-3]} // In Groovy you can index with a negative number in order to access from the end
CC4 slice == ${app.cc4_slice.getSolverUri()[-1]}
Register bitfield SRS.POSR == 0x${app.cc4_slice.getRegValue("srs", "srs_posr")}
SRS.POSR bitfield mask == 0x${Integer.toHexString(((Integer)app.cc4_slice.getRegOwnershipMask("srs_posr")))}
NVIC interrupt node == ${app.interrupt_node.getSolverUri()[-1]}
""")
}
**在DAVE™ 4中加载运行这个APP,可以生成:** CCU4 hardware module == 0
CC4 slice == 0
Register bitfield SRS.POSR == 0x2
SRS.POSR bitfield mask == 0x3
NVIC interrupt node == 46
![](http://img-storage.qiniudn.com/15-8-27/84555190.jpg) 你可以在DAVE™ SDK Device Explorer发现这些硬件,资源组,寄存器,字段位。你也可以发现solver自动设置的寄存器是红的。
返回顶部
##Deveice Explorer ## 8/25/2015 2:53 PM DAVE™ SDK Device Explorer是一个可以让你在开发APP过程中快速查找设备信息的有用工具。 它是一个单片机Datasheet的补充,你可以用它查找单片机的外设,管脚,包,来根据它来给出Manifest中resource group,信号,寄存器位字段的设置。
你可以通过Window → Open Perspective → Other → Device Explorer 找到Device Explorer的视图 . 打开视图后你要选择一种器件型号,接下来你会看到下面出现关于外设的这一栏目:
![](http://img-storage.qiniudn.com/15-8-24/1953202.jpg) 之后你可以查找任何一个在这些类别中的resource group 。举例来说,如果我们需要寻找一片CC4 在CCU4的Resource group中,为了知道它的位字段和提供的信号,我们可以如下面方式进行:
![](http://img-storage.qiniudn.com/15-8-25/14014756.jpg) 在这个例子里,我们只需要按下“CCU40”界面就会自动刷新,接下去我们单击“cc4/0”就会看到对应的片的位子段和信号。就如你所看到的,我们可以展开“cc4/0”它的resource group的URI 会在列表中出现。我们就可以把它复制下来用在manifest里。你也许知道,在单片机里有很多重复的硬件资源,我们使用APP的真正目的是不用去关心特定的硬件资源就可以充分利用它们aa。为了达到这一目的,我们用“*”或是solver的变量来替代固定的数字。用solver变量的好处是我们可以给它加条件约束在solver分配后可以访问它的值。
// Begin : User APP property section
MVirtualResourceGroup rg_example_resource_group
SolverVariable sv_group
// End : User APP property section
// App Constructor
public APP_NAME(DaveEnv daveEnv)
{
sv_group = SolverVariable()
addUriElementRangeConstraint(sv_group, [0,1]) // Only allows groups 0 and 1
rg_example_resource_group = MVirtualResourceGroup("Display name", ["ccu4", sv_group, "cc4", "*"])
}
在manifest中定义期望的resource group之后,你可以看到你定义的虚拟信号和访问位字段。
虚拟信号可以根据实际情况被其他信号所连接。连接的可能性能在Connect To 和Connect From 表中看到:
你也可以通过manifest 和templates文件来访问寄存器和寄存器的位字段。黑色字体的位字段可以被APP开发者所更改,但红色标注的寄存器只能根据APP用户的配置被solver自动分配。(e.g. 一个寄存器可以控制多路选择器来控制两信号的连接)。你可以在”Registers/Bit-Fields”看到寄存器包含的位字段:
想从寄存器返回值可以用:
MVirtualResourceGroup.getRegValue()
MVirtualResourceGroup.getRegOwnershipMask()
addRegisterBitFieldConstraint()
正确访问寄存器CCR中的HPCEN的方法是:
// Manifest code
// Begin : User APP property section
MVirtualResourceGroup usic_channel
// End : User APP property section
// APP Constructor
public TEST(DaveEnv daveEnv)
{
usic_channel = MVirtualResourceGroup("USIC Channel",["peripheral","usic","*","channel","*"])
}
// Template code
for(def app : appInstancesList)
{
def HPCEN = app.usic_channel.getRegValue("ccr", "ccr_hpcen")
}
Signal Design
信号设计器让开发者设计APP的单片机信号输出,最终它将会显示在用户终端上:DAVE™ 4中的“HW Signal Connectivity”视图中。这个文件在 -> Uimodel -> .sd.
在下面的例子中,我们使用GLOBAL_CCU8 APP 的APP作为例子,它有三个声明的有效的信号,在signal designer中我们可以设计这三个信号在DAVE™ 4 用户端的位置。我们可以最后通过声明MVirtualSignal参数来使得它在用户端不可见。其他的信号会在连接上后显示,它们会显示成灰色。
在上面显示的信号是在manifest中的MVirtualSignal 变量名中声明的。它会显示是因为当MVirtualSignal改变,上图会自动的改变。
根据设定信号的可视属性,一些信号在DAVE™ 4中不可见,所以如果可视属性被特定的设置,它可能在用户端不可见。
在DAVE™ 4中型号显示名是由在manifset 中的MVirtualSignal里“displayname”参数控制的。
返回顶部
Advanced Widegets
在这个教程中我们将会建立一个叫做GINDEXAPP的简单工程来展示怎么用GIndexGroup和GIndexCombo。我们假设你已经了解前文中APP开发的过程。
GindexGroup可以让你给窗体部件归类,GIndexCombo就像一个指针让你可以在不同的GindexGroup中切换来减少窗体的占用面积和在生成APP GUI时占用更少的资源来使APP的运行效果更佳。
在下面的图中你可以比较普通的布置方案和用GindexGroup的不同。如果在这个例子里你只有5个相似的部件,或许你想同时显示它们,设想你如果有6个部件你就没有其余的空间来放置它,你只能把它们放在不同的Tab上,这不是一个好的解决方案。
尽管使用GIndexGroup和GIndexCombo 是进阶的教程,但它们不难。本质上,GIndexCombo就是GIndexGroup的选择器。
当你创建一个GIndexGroup,你需要拖一个GIndexCombo且只有一个在窗体里,之后你可以拖任何你想要的窗体部件进去。然后你就能马上得到GIndexCombo的最多能产生的数目。保存后,你将在manifest文件中看到一个.wg文件。
这个新的文件包含了你刚刚加入的窗体部件:
import ifx.davex.app.manifest.*;
class Gindexgroup_example {
public GCombo gcombo_example;
public GInteger ginteger_example;
public GCheck gcheck_example;
public Gindexgroup_example (DaveEnv daveEnv, String widgetName, int index){
gcombo_example = new GCombo(widgetName:"gcombo_example", options:["Option 1","Option 2"], value:"Option 1", enabled:true, visible:true, isMandatoryValue:false , parentWidgetName:widgetName)
ginteger_example = new GInteger(widgetName:"ginteger_example", value:1024, minValue:0, maxValue:4096, enabled:true, visible:true, isMandatoryValue:false , parentWidgetName:widgetName)
gcheck_example = new GCheck(widgetName:"gcheck_example", value:false, enabled:true, visible:true, parentWidgetName:widgetName)
}
}
在此同时,一些新的代码在GINDEXAPP_GUI.manifest文件中生成:
abstract class GINDEXAPP_GUI extends AppManifest {
// Begin : UI variable section
public GInteger ginteger_number_of_items;
public GIndexCombo gindexcombo_item;
public GIndexGroup gindexgroup_example;
public RArray rArraygindexgroup_example = RArray(16);
public GINDEXAPP_GUI(DaveEnv daveEnv){
ginteger_number_of_items = GInteger(widgetName:"ginteger_number_of_items", value:5, minValue:1, maxValue:16, enabled:true, visible:true, isMandatoryValue:false)
gindexcombo_item = GIndexCombo(widgetName:"gindexcombo_item", options:["ITEM_0","ITEM_1","ITEM_2","ITEM_3","ITEM_4","ITEM_5","ITEM_6","ITEM_7","ITEM_8","ITEM_9","ITEM_10","ITEM_11","ITEM_12","ITEM_13","ITEM_14","ITEM_15"], value:"ITEM_0")
gindexgroup_example = GIndexGroup(widgetName:"gindexgroup_example", text:"GIndexGroup", enabled:true, visible:true, gIndexCombo:gindexcombo_item, rArray:rArraygindexgroup_example)
for(int i=0; i
#ifndef _GINDEXAPP_H_
#define _GINDEXAPP_H_
#ifdef __cplusplus
extern "C" {
#endif
/***********************************************************************************************************************
** System Header file inclusion **
***********************************************************************************************************************/
#include
#include "GINDEXAPP_extern.h" /* Included to access the APP Handles at Main.c */
#ifdef __cplusplus
}
#endif
#endif /* GINDEXAPP_H_ */
gindexapp_extern_h.tmpl file:
out.print("""
#ifndef GINDEXAPP_EXTERN_H_
#define GINDEXAPP_EXTERN_H_
#ifdef __cplusplus
extern "C" {
#endif
/* Extern declaration of GINDEXAPP APP handlers */
""")
for(def app : appInstancesList){
for (int i = 0; i
#ifdef __cplusplus
}
#endif
#endif /* GINDEXAPP_EXTERN_H_ */""")
gindexapp_conf_c.tmpl file:
out.println("#include \"gindexapp.h\"")
for (GINDEXAPP app : appInstancesList)
{
for (int i = 0; i
#ifndef GINDEXAPP_EXTERN_H_
#define GINDEXAPP_EXTERN_H_
#ifdef __cplusplus
extern "C" {
#endif
/* Extern declaration of GINDEXAPP APP handlers */
extern GINDEXAPP_t GINDEXAPP_0_ITEM_0;
extern GINDEXAPP_t GINDEXAPP_0_ITEM_1;
extern GINDEXAPP_t GINDEXAPP_1_ITEM_0;
#ifdef __cplusplus
}
#endif
#endif /* GINDEXAPP_EXTERN_H_ */
gindexapp_conf.c file:
#include "gindexapp.h"
GINDEXAPP_t GINDEXAPP_0_ITEM_0 =
{
.gcombo = "Option 1",
.ginteger = 3210,
.gcheck = true
};
GINDEXAPP_t GINDEXAPP_0_ITEM_1 =
{
.gcombo = "Option 1",
.ginteger = 1024,
.gcheck = false
};
GINDEXAPP_t GINDEXAPP_1_ITEM_0 =
{
.gcombo = "Option 2",
.ginteger = 83,
.gcheck = false
};