Commit f76a575b authored by Federico Vaga's avatar Federico Vaga

sw:fw:frm: add app operations to execute firmware code

something like Arduino. This allows us to execute special code
before or after each operation
Signed-off-by: Federico Vaga's avatarFederico Vaga <federico.vaga@cern.ch>
parent 352a1d7a
...@@ -46,17 +46,6 @@ static struct trtl_fw_variable variables[] = { ...@@ -46,17 +46,6 @@ static struct trtl_fw_variable variables[] = {
}, },
}; };
static struct trtl_fw_application app = {
.name = "alarm-clk",
.version = {
.rt_id = CONFIG_RT_APPLICATION_ID,
.rt_version = RT_VERSION(0, 1),
.git_version = GIT_VERSION
},
.variables = variables,
.n_variables = ARRAY_SIZE(variables),
};
static void ac_update(void) static void ac_update(void)
...@@ -88,20 +77,19 @@ static void ac_update(void) ...@@ -88,20 +77,19 @@ static void ac_update(void)
/** /**
* Firmware initialization * Firmware initialization
*/ */
static void ac_init(void) static int ac_init(void)
{ {
period_c = period; period_c = period;
return 0;
} }
/** /**
* Well, the main :) * Well, the main :)
*/ */
int main() static int ac_main(void)
{ {
trtl_fw_init(&app);
ac_init();
while (1) { while (1) {
/* Handle all messages incoming from HMQ 0 as actions */ /* Handle all messages incoming from HMQ 0 as actions */
trtl_fw_mq_action_dispatch(TRTL_HMQ, 0); trtl_fw_mq_action_dispatch(TRTL_HMQ, 0);
...@@ -111,3 +99,19 @@ int main() ...@@ -111,3 +99,19 @@ int main()
return 0; return 0;
} }
struct trtl_fw_application app = {
.name = "alarm-clk",
.version = {
.rt_id = CONFIG_RT_APPLICATION_ID,
.rt_version = RT_VERSION(0, 1),
.git_version = GIT_VERSION
},
.variables = variables,
.n_variables = ARRAY_SIZE(variables),
.init = ac_init,
.main = ac_main,
};
...@@ -51,20 +51,6 @@ struct trtl_fw_buffer buffers[] = { ...@@ -51,20 +51,6 @@ struct trtl_fw_buffer buffers[] = {
}, },
}; };
static struct trtl_fw_application app = {
.name = "data-gen",
.version = {
.rt_id = CONFIG_RT_APPLICATION_ID,
.rt_version = RT_VERSION(0, 1),
.git_version = GIT_VERSION
},
.variables = variables,
.n_variables = ARRAY_SIZE(variables),
.buffers = buffers,
.n_buffers = ARRAY_SIZE(buffers),
};
static void generate_sample(void) static void generate_sample(void)
{ {
...@@ -98,24 +84,23 @@ static void dg_update(void) ...@@ -98,24 +84,23 @@ static void dg_update(void)
/** /**
* Firmware initialization * Firmware initialization
*/ */
static void dg_init(void) static int dg_init(void)
{ {
period_c = period; period_c = period;
dg_last_sample_idx = 0; dg_last_sample_idx = 0;
dg_last_sample = 1; dg_last_sample = 1;
dg_conf.offset = 0; dg_conf.offset = 0;
dg_conf.gain = 1; dg_conf.gain = 1;
return 0;
} }
/** /**
* Well, the main :) * Well, the main :)
*/ */
int main() static int dg_main()
{ {
trtl_fw_init(&app);
dg_init();
while (1) { while (1) {
/* Handle all messages incoming from HMQ 0 as actions */ /* Handle all messages incoming from HMQ 0 as actions */
trtl_fw_mq_action_dispatch(TRTL_HMQ, 0); trtl_fw_mq_action_dispatch(TRTL_HMQ, 0);
...@@ -125,3 +110,22 @@ int main() ...@@ -125,3 +110,22 @@ int main()
return 0; return 0;
} }
struct trtl_fw_application app = {
.name = "data-gen",
.version = {
.rt_id = CONFIG_RT_APPLICATION_ID,
.rt_version = RT_VERSION(0, 1),
.git_version = GIT_VERSION
},
.variables = variables,
.n_variables = ARRAY_SIZE(variables),
.buffers = buffers,
.n_buffers = ARRAY_SIZE(buffers),
.init = dg_init,
.main = dg_main,
};
...@@ -68,40 +68,24 @@ struct trtl_fw_variable svec_variables[] = { ...@@ -68,40 +68,24 @@ struct trtl_fw_variable svec_variables[] = {
}; };
struct trtl_fw_application app = {
.name = "manualsvec",
.version = {
.rt_id = RT_APPLICATION_ID,
.rt_version = RT_VERSION(1, 0),
.git_version = GIT_VERSION
},
.buffers = svec_buffers,
.n_buffers = ARRAY_SIZE(svec_buffers),
.variables = svec_variables,
.n_variables = ARRAY_SIZE(svec_variables),
};
/** /**
* It sends messages over the debug interface * It sends messages over the debug interface
*/ */
static void svec_debug_interface(void) static int svec_debug_interface(void)
{ {
pp_printf("Hello world.\n\r"); pp_printf("Hello world.\n\r");
pp_printf("We are messages over the serial interface.\n\r"); pp_printf("We are messages over the serial interface.\n\r");
pp_printf("Print here your messages.\n\r"); pp_printf("Print here your messages.\n\r");
return 0;
} }
/** /**
* Well, the main :) * Well, the main :)
*/ */
int main() static int svec_main()
{ {
trtl_fw_init(&app);
svec_debug_interface();
while (1) { while (1) {
/* Handle all messages incoming from HMQ 0 as actions */ /* Handle all messages incoming from HMQ 0 as actions */
trtl_fw_mq_action_dispatch(TRTL_HMQ, 0); trtl_fw_mq_action_dispatch(TRTL_HMQ, 0);
...@@ -109,3 +93,22 @@ int main() ...@@ -109,3 +93,22 @@ int main()
return 0; return 0;
} }
struct trtl_fw_application app = {
.name = "manualsvec",
.version = {
.rt_id = RT_APPLICATION_ID,
.rt_version = RT_VERSION(1, 0),
.git_version = GIT_VERSION
},
.buffers = svec_buffers,
.n_buffers = ARRAY_SIZE(svec_buffers),
.variables = svec_variables,
.n_variables = ARRAY_SIZE(svec_variables),
.init = svec_debug_interface,
.main = svec_main,
};
...@@ -6,22 +6,18 @@ ...@@ -6,22 +6,18 @@
#include <mockturtle-framework.h> #include <mockturtle-framework.h>
static struct trtl_fw_application app = { static int frm_init()
.name = "hellofrm", {
.version = { pp_printf("Hello world!\r\n");
.rt_id = CONFIG_RT_APPLICATION_ID,
.rt_version = RT_VERSION(0, 1), return 0;
.git_version = GIT_VERSION, }
},
};
/** /**
* Well, the main :) * Well, the main :)
*/ */
int main() static int frm_main()
{ {
trtl_fw_init(&app);
while (1) { while (1) {
/* /*
* Handle all messages incoming from slot 0 * Handle all messages incoming from slot 0
...@@ -32,3 +28,16 @@ int main() ...@@ -32,3 +28,16 @@ int main()
return 0; return 0;
} }
struct trtl_fw_application app = {
.name = "hellofrm",
.version = {
.rt_id = CONFIG_RT_APPLICATION_ID,
.rt_version = RT_VERSION(0, 1),
.git_version = GIT_VERSION,
},
.init = frm_init,
.main = frm_main,
};
...@@ -25,11 +25,46 @@ Application ...@@ -25,11 +25,46 @@ Application
=========== ===========
Firmwares developed with this framework need to be described by Firmwares developed with this framework need to be described by
:c:type:`trtl_fw_application`. You should declare a new :c:type:`trtl_fw_application` :c:type:`trtl_fw_application`. Firmware applications develop with this
and initialize it using :c:func:`trtl_fw_init` .:: framework does not have a ``main()``. The ``main()`` is implemented within the
framework itself. What you should do is to declare a new
:c:type:`trtl_fw_application` named **app** and implement the operations
*init*, *main* and *exit*. These operations are all optional, it means that if
you do not implement them nothing will be executed.
.. graphviz::
:align: center
:caption: Mock Turtle Firmware Framework Phases.
digraph phases {
init -> main;
main -> exit;
}
Here an example.::
#include <mockturtle-framework.h> #include <mockturtle-framework.h>
static init myinit()
{
return 0;
}
static int mymain()
{
while (1) {
/* main code here */
}
return 0;
}
static init myexit()
{
return 0;
}
struct trtl_application app = { struct trtl_application app = {
.name = "myfirmware", .name = "myfirmware",
.fpga_id_compat = NULL, .fpga_id_compat = NULL,
...@@ -39,14 +74,12 @@ and initialize it using :c:func:`trtl_fw_init` .:: ...@@ -39,14 +74,12 @@ and initialize it using :c:func:`trtl_fw_init` .::
.version = RT_VERSION(1, 0), .version = RT_VERSION(1, 0),
.git = GIT_VERSION, .git = GIT_VERSION,
}, },
};
int main() .init = myinit,
{ .main = mymain,
trtl_dw_init(&app); .exit = myexit,
};
return 0;
}
The Mock Turtle is FPGA based, this means that the firmwares are The Mock Turtle is FPGA based, this means that the firmwares are
typically loaded by the host. The procedure is error prone, so it may typically loaded by the host. The procedure is error prone, so it may
...@@ -63,8 +96,6 @@ not provide a compatibility list (like in the example above). ...@@ -63,8 +96,6 @@ not provide a compatibility list (like in the example above).
.. doxygenstruct:: trtl_fw_version .. doxygenstruct:: trtl_fw_version
:members: :members:
.. doxygenfunction:: trtl_fw_init
Actions Actions
======== ========
...@@ -122,19 +153,9 @@ RPC messages on a given mq. Here an example.:: ...@@ -122,19 +153,9 @@ RPC messages on a given mq. Here an example.::
/* ... */ /* ... */
}; };
/* POINT [4]*/ static int mymain()
struct trtl_application app = {
/* ... */
/* Export Actions */
.actions = actions,
.n_actions = ARRAY_SIZE(actions),
};
int main()
{ {
int err; int err;
trtl_fw_init(&app);
while (1) { while (1) {
/* ... */ /* ... */
...@@ -145,6 +166,19 @@ RPC messages on a given mq. Here an example.:: ...@@ -145,6 +166,19 @@ RPC messages on a given mq. Here an example.::
return 0; return 0;
} }
/* POINT [4]*/
struct trtl_application app = {
/* ... */
/* Export Actions */
.actions = actions,
.n_actions = ARRAY_SIZE(actions),
.main = mymain,
};
.. doxygentypedef:: trtl_fw_action_t .. doxygentypedef:: trtl_fw_action_t
.. doxygenfunction:: trtl_fw_mq_action_dispatch .. doxygenfunction:: trtl_fw_mq_action_dispatch
...@@ -195,14 +229,7 @@ be used to dispatch incoming actions:: ...@@ -195,14 +229,7 @@ be used to dispatch incoming actions::
}, },
}; };
struct trtl_fw_application app = { static int mymain()
/* ... */
.variables = variables,
.n_variable = ARRAY_SIZE(variables),
};
int main()
{ {
/* ... */ /* ... */
...@@ -214,6 +241,15 @@ be used to dispatch incoming actions:: ...@@ -214,6 +241,15 @@ be used to dispatch incoming actions::
return 0; return 0;
} }
struct trtl_fw_application app = {
/* ... */
.variables = variables,
.n_variable = ARRAY_SIZE(variables),
.main = mymain,
};
The user can define any number of variables, the firmware framework does The user can define any number of variables, the firmware framework does
not impose any constraint. not impose any constraint.
...@@ -269,18 +305,8 @@ be used to dispatch incoming actions:: ...@@ -269,18 +305,8 @@ be used to dispatch incoming actions::
}, },
}; };
/* ... */
struct trtl_fw_application app = {
/* ... */
.buffers = buffers,
.n_buffer = ARRAY_SIZE(buffers),
};
static int mymain()
int main()
{ {
/* ... */ /* ... */
...@@ -292,6 +318,15 @@ be used to dispatch incoming actions:: ...@@ -292,6 +318,15 @@ be used to dispatch incoming actions::
return 0; return 0;
} }
struct trtl_fw_application app = {
/* ... */
.buffers = buffers,
.n_buffer = ARRAY_SIZE(buffers),
.main = mymain,
};
The user can define any number of buffers, the firmware framework does The user can define any number of buffers, the firmware framework does
not impose any constraint. not impose any constraint.
......
...@@ -11,7 +11,6 @@ ...@@ -11,7 +11,6 @@
#include <mockturtle-framework.h> #include <mockturtle-framework.h>
uint32_t msg_seq = 0; uint32_t msg_seq = 0;
struct trtl_fw_application *_app;
/** /**
* It makes the given message an error message * It makes the given message an error message
...@@ -42,7 +41,7 @@ static int rt_version_getter(struct trtl_fw_msg *msg_i, struct trtl_fw_msg *msg_ ...@@ -42,7 +41,7 @@ static int rt_version_getter(struct trtl_fw_msg *msg_i, struct trtl_fw_msg *msg_
{ {
msg_o->header->msg_id = TRTL_MSG_ID_VER; msg_o->header->msg_id = TRTL_MSG_ID_VER;
msg_o->header->len = sizeof(struct trtl_fw_version) / 4; msg_o->header->len = sizeof(struct trtl_fw_version) / 4;
memcpy(msg_o->payload, (void *)&_app->version, memcpy(msg_o->payload, (void *)&app.version,
sizeof(struct trtl_fw_version)); sizeof(struct trtl_fw_version));
return 0; return 0;
} }
...@@ -79,15 +78,15 @@ static int trtl_fw_buffer_getter(struct trtl_fw_msg *msg_i, struct trtl_fw_msg * ...@@ -79,15 +78,15 @@ static int trtl_fw_buffer_getter(struct trtl_fw_msg *msg_i, struct trtl_fw_msg *
size = din[offset]; size = din[offset];
dout[offset++] = size; dout[offset++] = size;
pr_debug("%s Type %d Len %d Addr 0x%p\n\r", __func__, pr_debug("%s Type %d Len %d Addr 0x%p\n\r", __func__,
index, size, _app->buffers[index].buf); index, size, app.buffers[index].buf);
if (_app->buffers[index].len == size) { if (app.buffers[index].len == size) {
memcpy(&dout[offset], memcpy(&dout[offset],
(uint32_t *)_app->buffers[index].buf, (uint32_t *)app.buffers[index].buf,
size); size);
} else { } else {
pr_error("%s: structure %d len not correct %"PRId32" != %d\n\r", pr_error("%s: structure %d len not correct %"PRId32" != %d\n\r",
__func__, index, _app->buffers[index].len, size); __func__, index, app.buffers[index].len, size);
} }
offset += (size / 4); /* Next TLV record */ offset += (size / 4); /* Next TLV record */
...@@ -121,15 +120,15 @@ static int trtl_fw_buffer_setter(struct trtl_fw_msg *msg_i, struct trtl_fw_msg * ...@@ -121,15 +120,15 @@ static int trtl_fw_buffer_setter(struct trtl_fw_msg *msg_i, struct trtl_fw_msg *
size = din[offset++]; size = din[offset++];
pr_debug("%s Type %d Len %d Addr 0x%p\n\r", __func__, pr_debug("%s Type %d Len %d Addr 0x%p\n\r", __func__,
index, size, _app->buffers[index].buf); index, size, app.buffers[index].buf);
if (_app->buffers[index].len == size) { if (app.buffers[index].len == size) {
memcpy((uint32_t *)_app->buffers[index].buf, memcpy((uint32_t *)app.buffers[index].buf,
&din[offset], size); &din[offset], size);
} else { } else {
pr_error("%s:%d structure %d len not correct %"PRId32" != %d\n\r", pr_error("%s:%d structure %d len not correct %"PRId32" != %d\n\r",
__func__, __LINE__, index, __func__, __LINE__, index,
_app->buffers[index].len, size); app.buffers[index].len, size);
} }
offset += (size / 4); /* Next TLV record */ offset += (size / 4); /* Next TLV record */
...@@ -173,19 +172,19 @@ static int trtl_fw_variable_getter(struct trtl_fw_msg *msg_i, struct trtl_fw_msg ...@@ -173,19 +172,19 @@ static int trtl_fw_variable_getter(struct trtl_fw_msg *msg_i, struct trtl_fw_msg
/* Write all values in the proper place */ /* Write all values in the proper place */
for (i = 0; i < msg_o->header->len; i += 2) { for (i = 0; i < msg_o->header->len; i += 2) {
if (din[i] >= _app->n_variables) { if (din[i] >= app.n_variables) {
dout[i] = ~0; /* Report invalid index */ dout[i] = ~0; /* Report invalid index */
continue; continue;
} }
dout[i] = din[i]; dout[i] = din[i];
var = &_app->variables[dout[i]]; var = &app.variables[dout[i]];
mem = (uint32_t *) var->addr; mem = (uint32_t *) var->addr;
val = (*mem >> var->offset) & var->mask; val = (*mem >> var->offset) & var->mask;
dout[i + 1] = val; dout[i + 1] = val;
pr_debug("%s index %"PRIu32"d/%d | [0x%p] = 0x%08"PRIx32" -> 0x%08"PRIx32" | index in msg (%d/%d)\n\r", pr_debug("%s index %"PRIu32"d/%d | [0x%p] = 0x%08"PRIx32" -> 0x%08"PRIx32" | index in msg (%d/%d)\n\r",
__func__, __func__,
dout[i], _app->n_variables - 1, dout[i], app.n_variables - 1,
mem, *mem, dout[i + 1], mem, *mem, dout[i + 1],
i + 1, msg_i->header->len - 1); i + 1, msg_i->header->len - 1);
} }
...@@ -217,9 +216,9 @@ static int trtl_fw_variable_setter(struct trtl_fw_msg *msg_i, struct trtl_fw_msg ...@@ -217,9 +216,9 @@ static int trtl_fw_variable_setter(struct trtl_fw_msg *msg_i, struct trtl_fw_msg
/* Write all values in the proper place */ /* Write all values in the proper place */
for (i = 0; i < msg_i->header->len; i += 2) { for (i = 0; i < msg_i->header->len; i += 2) {
if (din[i] >= _app->n_variables) if (din[i] >= app.n_variables)
continue; continue;
var = &_app->variables[din[i]]; var = &app.variables[din[i]];
mem = (uint32_t *) var->addr; mem = (uint32_t *) var->addr;
val = ((din[i + 1] & var->mask) << var->offset); val = ((din[i + 1] & var->mask) << var->offset);
if (var->flags & TRTL_FW_VARIABLE_FLAG_FLD) if (var->flags & TRTL_FW_VARIABLE_FLAG_FLD)
...@@ -229,7 +228,7 @@ static int trtl_fw_variable_setter(struct trtl_fw_msg *msg_i, struct trtl_fw_msg ...@@ -229,7 +228,7 @@ static int trtl_fw_variable_setter(struct trtl_fw_msg *msg_i, struct trtl_fw_msg
pr_debug("%s index %"PRIu32"/%d | [0x%p] = 0x%08"PRIx32" <- 0x%08"PRIx32" (0x%08"PRIx32") | index in msg (%d/%d)\n\r", pr_debug("%s index %"PRIu32"/%d | [0x%p] = 0x%08"PRIx32" <- 0x%08"PRIx32" (0x%08"PRIx32") | index in msg (%d/%d)\n\r",
__func__, __func__,
din[i], _app->n_variables - 1, din[i], app.n_variables - 1,
mem, *mem, val, din[i + 1], mem, *mem, val, din[i + 1],
i + 1, msg_i->header->len - 1); i + 1, msg_i->header->len - 1);
} }
...@@ -267,12 +266,12 @@ static inline trtl_fw_action_t *rt_action_get(unsigned int msg_id) ...@@ -267,12 +266,12 @@ static inline trtl_fw_action_t *rt_action_get(unsigned int msg_id)
if (idx_act < __TRTL_MSG_ID_MAX_USER) { if (idx_act < __TRTL_MSG_ID_MAX_USER) {
/* User Actions */ /* User Actions */
if (idx_act >= _app->n_actions || !_app->actions[idx_act]) { if (idx_act >= app.n_actions || !app.actions[idx_act]) {
pr_error("Unknown action (usr) msg_id 0x%x\n\r", pr_error("Unknown action (usr) msg_id 0x%x\n\r",
msg_id); msg_id);
return NULL; return NULL;
} }
return _app->actions[idx_act]; return app.actions[idx_act];
} else { } else {
/* Mock Turtle Standard Actions */ /* Mock Turtle Standard Actions */
idx_act -= __TRTL_MSG_ID_MAX_USER; idx_act -= __TRTL_MSG_ID_MAX_USER;
...@@ -316,12 +315,12 @@ static inline int rt_action_run(enum trtl_mq_type type, ...@@ -316,12 +315,12 @@ static inline int rt_action_run(enum trtl_mq_type type,
mq_map_out_message(type, idx_mq, &msg_out); mq_map_out_message(type, idx_mq, &msg_out);
/* prepare the header */ /* prepare the header */
msg_out.header->rt_app_id = _app->version.rt_id; msg_out.header->rt_app_id = app.version.rt_id;
msg_out.header->flags = TRTL_HMQ_HEADER_FLAG_ACK; msg_out.header->flags = TRTL_HMQ_HEADER_FLAG_ACK;
msg_out.header->msg_id = 0; msg_out.header->msg_id = 0;
msg_out.header->len = 0; msg_out.header->len = 0;
msg_out.header->sync_id = msg->header->sync_id; msg_out.header->sync_id = msg->header->sync_id;
msg_out.header->seq = _app->seq++; msg_out.header->seq = app.seq++;
err = action(msg, &msg_out); err = action(msg, &msg_out);
if (err) if (err)
...@@ -363,7 +362,7 @@ int trtl_fw_mq_action_dispatch(enum trtl_mq_type type, unsigned int idx_mq) ...@@ -363,7 +362,7 @@ int trtl_fw_mq_action_dispatch(enum trtl_mq_type type, unsigned int idx_mq)
} }
if (msg.header->rt_app_id && if (msg.header->rt_app_id &&
msg.header->rt_app_id != _app->version.rt_id) { msg.header->rt_app_id != app.version.rt_id) {
pr_error("Invalid app id 0x%x\n\r", pr_error("Invalid app id 0x%x\n\r",
msg.header->rt_app_id); msg.header->rt_app_id);
err = -EINVAL; err = -EINVAL;
...@@ -398,18 +397,18 @@ int trtl_fw_mq_send_uint32(enum trtl_mq_type type, ...@@ -398,18 +397,18 @@ int trtl_fw_mq_send_uint32(enum trtl_mq_type type,
va_list ap; va_list ap;
int i; int i;
sizes = _app->cfgrom->hmq[trtl_get_core_id()][idx_mq].sizes; sizes = app.cfgrom->hmq[trtl_get_core_id()][idx_mq].sizes;
if (n > TRTL_CONFIG_ROM_MQ_SIZE_PAYLOAD(sizes)) if (n > TRTL_CONFIG_ROM_MQ_SIZE_PAYLOAD(sizes))
return -EINVAL; return -EINVAL;
mq_claim(type, idx_mq); mq_claim(type, idx_mq);
mq_map_out_message(type, idx_mq, &msg); mq_map_out_message(type, idx_mq, &msg);
msg.header->rt_app_id = _app->version.rt_id; msg.header->rt_app_id = app.version.rt_id;
msg.header->flags = 0; msg.header->flags = 0;
msg.header->msg_id = msg_id; msg.header->msg_id = msg_id;
msg.header->len = n; msg.header->len = n;
msg.header->seq = _app->seq++; msg.header->seq = app.seq++;
va_start(ap, n); va_start(ap, n);
for (i = 0; i < msg.header->len;++i) for (i = 0; i < msg.header->len;++i)
...@@ -441,18 +440,18 @@ int trtl_fw_mq_send_buf(enum trtl_mq_type type, ...@@ -441,18 +440,18 @@ int trtl_fw_mq_send_buf(enum trtl_mq_type type,
struct trtl_fw_msg msg; struct trtl_fw_msg msg;
uint32_t sizes; uint32_t sizes;
sizes = _app->cfgrom->hmq[trtl_get_core_id()][idx_mq].sizes; sizes = app.cfgrom->hmq[trtl_get_core_id()][idx_mq].sizes;
if ((n / 4) > TRTL_CONFIG_ROM_MQ_SIZE_PAYLOAD(sizes)) if ((n / 4) > TRTL_CONFIG_ROM_MQ_SIZE_PAYLOAD(sizes))
return -EINVAL; return -EINVAL;
mq_claim(type, idx_mq); mq_claim(type, idx_mq);
mq_map_out_message(type, idx_mq, &msg); mq_map_out_message(type, idx_mq, &msg);
msg.header->rt_app_id = _app->version.rt_id; msg.header->rt_app_id = app.version.rt_id;
msg.header->flags = 0; msg.header->flags = 0;
msg.header->msg_id = msg_id; msg.header->msg_id = msg_id;
msg.header->len = n / 4; msg.header->len = n / 4;
msg.header->seq = _app->seq++; msg.header->seq = app.seq++;
memcpy(msg.payload, data, n); memcpy(msg.payload, data, n);
mq_send(type, idx_mq); mq_send(type, idx_mq);
...@@ -536,13 +535,13 @@ static inline int trtl_fw_init_action(struct trtl_fw_application *app) ...@@ -536,13 +535,13 @@ static inline int trtl_fw_init_action(struct trtl_fw_application *app)
int i; int i;
/* Validate actions */ /* Validate actions */
for (i = 0; i < _app->n_actions; ++i) { for (i = 0; i < app->n_actions; ++i) {
if (i > __TRTL_MSG_ID_MAX_USER) { if (i > __TRTL_MSG_ID_MAX_USER) {
pr_error("Too many actions defined. Maximum '%d'\n\r", pr_error("Too many actions defined. Maximum '%d'\n\r",
__TRTL_MSG_ID_MAX_USER); __TRTL_MSG_ID_MAX_USER);
return -EINVAL; return -EINVAL;
} }
if (_app->actions[i] == NULL) { if (app->actions[i] == NULL) {
pr_error("Undefined action %d\n\r", i); pr_error("Undefined action %d\n\r", i);
return -EINVAL; return -EINVAL;
} }
...@@ -650,33 +649,67 @@ static inline int trtl_fw_init_buffers(struct trtl_fw_application *app) ...@@ -650,33 +649,67 @@ static inline int trtl_fw_init_buffers(struct trtl_fw_application *app)
* @param[in] app application to initialize * @param[in] app application to initialize
* @return 0 on success. -1 on error * @return 0 on success. -1 on error
*/ */
int trtl_fw_init(struct trtl_fw_application *app) int trtl_fw_init(void)
{ {
int err; int err;
_app = app; app.seq = 0;
_app->seq = 0; app.cfgrom = trtl_config_rom_get();
_app->cfgrom = trtl_config_rom_get();
err = trtl_fw_init_action(_app); err = trtl_fw_init_action(&app);
if (err) if (err)
return err; return err;
err = trtl_fw_init_fpga(_app); err = trtl_fw_init_fpga(&app);
if (err) if (err)
return err; return err;
err = trtl_fw_init_mq(_app); err = trtl_fw_init_mq(&app);
if (err) if (err)
return err; return err;
err = trtl_fw_init_buffers(_app); err = trtl_fw_init_buffers(&app);
if (err) if (err)
return err; return err;
err = trtl_fw_init_variables(_app); err = trtl_fw_init_variables(&app);
if (err) if (err)
return err; return err;
return 0; return 0;
} }
/**
* The main function
*/
int main(void)
{
int err = 0;
trtl_notify(TRTL_CPU_NOTIFY_INIT);
trtl_fw_init();
if (app.init){
err = app.init();
if (err)
return -1;
}
trtl_notify(TRTL_CPU_NOTIFY_MAIN);
if (app.main) {
err = app.main();
if (err)
return -1;
}
trtl_notify(TRTL_CPU_NOTIFY_EXIT);
if (app.exit) {
err = app.exit();
if (err)
return -1;
}
return 0;
}
...@@ -29,6 +29,13 @@ ...@@ -29,6 +29,13 @@
*/ */
typedef int (trtl_fw_action_t)(struct trtl_fw_msg *msg_i, struct trtl_fw_msg *msg_o); typedef int (trtl_fw_action_t)(struct trtl_fw_msg *msg_i, struct trtl_fw_msg *msg_o);
/**
* Application phase
* @return 0 on success. -1 on error
*/
typedef int (trtl_fw_phase_t)(void);
/** /**
* Variable flag. Register * Variable flag. Register
*/ */
...@@ -81,12 +88,29 @@ struct trtl_fw_application { ...@@ -81,12 +88,29 @@ struct trtl_fw_application {
unsigned int seq; /** sequence number reference */ unsigned int seq; /** sequence number reference */
const struct trtl_config_rom *cfgrom; /**< configuration ROM */ const struct trtl_config_rom *cfgrom; /**< configuration ROM */
/* Operations */
trtl_fw_phase_t *init; /**< function where you prepare
the application */
trtl_fw_phase_t *main; /**< function where you execute your
application */
trtl_fw_phase_t *exit; /**< function where you clean-up firmware
status */
}; };
extern struct trtl_fw_application *_app; extern struct trtl_fw_application app;
/**
* It returns the application descriptor
* @return application descriptor
*/
static inline struct trtl_fw_application *trtl_fw_application_get(void)
{
return &app;
}
extern int trtl_fw_init(struct trtl_fw_application *app);
extern void trtl_fw_time(uint32_t *seconds, uint32_t *cycles); extern void trtl_fw_time(uint32_t *seconds, uint32_t *cycles);
extern void trtl_fw_print_header(struct trtl_hmq_header *h); extern void trtl_fw_print_header(struct trtl_hmq_header *h);
extern void trtl_fw_print_data(uint32_t *d, unsigned int count); extern void trtl_fw_print_data(uint32_t *d, unsigned int count);
......
...@@ -41,6 +41,11 @@ ...@@ -41,6 +41,11 @@
enum trtl_cpu_notification { enum trtl_cpu_notification {
TRTL_CPU_NOTIFY_APPLICATION = 0, /**< anonymous application TRTL_CPU_NOTIFY_APPLICATION = 0, /**< anonymous application
notification (user) */ notification (user) */
TRTL_CPU_NOTIFY_INIT, /**< the firmware is executing init phase */
TRTL_CPU_NOTIFY_MAIN, /**< the firmware is executing main phase */
TRTL_CPU_NOTIFY_EXIT, /**< the firmware is executing exit finishing */
TRTL_CPU_NOTIFY_ERR, /**< general error, firmware is not running
anymore */
__TRTL_CPU_NOTIFY_MAX, __TRTL_CPU_NOTIFY_MAX,
}; };
......
...@@ -28,31 +28,20 @@ static trtl_fw_action_t *actions[] = { ...@@ -28,31 +28,20 @@ static trtl_fw_action_t *actions[] = {
}; };
static struct trtl_fw_application app = { /**
.name = "{{short_name}}", * Initialization code
.version = { */
.rt_id = CONFIG_RT_APPLICATION_ID, static int {{short_name}}_init()
.rt_version = RT_VERSION(0, 1), {
.git_version = GIT_VERSION return 0;
}, }
.buffers = buffers,
.n_buffers = ARRAY_SIZE(buffers),
.variables = variables,
.n_variables = ARRAY_SIZE(variables),
.actions = actions,
.n_actions = ARRAY_SIZE(actions),
};
/** /**
* Well, the main :) * Well, the main :)
*/ */
int main() static int {{short_name}}_main()
{ {
trtl_fw_init(&app);
while (1) { while (1) {
/* /*
* Handle all messages incoming from slot * Handle all messages incoming from slot
...@@ -63,3 +52,34 @@ int main() ...@@ -63,3 +52,34 @@ int main()
return 0; return 0;
} }
/**
* Exit code
*/
static int {{short_name}}_exit()
{
return 0;
}
struct trtl_fw_application app = {
.name = "{{short_name}}",
.version = {
.rt_id = CONFIG_RT_APPLICATION_ID,
.rt_version = RT_VERSION(0, 1),
.git_version = GIT_VERSION
},
.buffers = buffers,
.n_buffers = ARRAY_SIZE(buffers),
.variables = variables,
.n_variables = ARRAY_SIZE(variables),
.actions = actions,
.n_actions = ARRAY_SIZE(actions),
.init = {{short_name}}_init,
.main = {{short_name}}_main,
.exit = {{short_name}}_exit,
};
...@@ -6,22 +6,12 @@ ...@@ -6,22 +6,12 @@
#include <mockturtle-framework.h> #include <mockturtle-framework.h>
static struct trtl_fw_application app = {
.name = "hellofrm",
.version = {
.rt_id = CONFIG_RT_APPLICATION_ID,
.rt_version = RT_VERSION(0, 1),
.git_version = GIT_VERSION
},
};
/** /**
* Well, the main :) * Well, the main :)
*/ */
int main() static int ping_main()
{ {
trtl_fw_init(&app);
while (1) { while (1) {
/* Handle all messages incoming from HMQ 0 as actions */ /* Handle all messages incoming from HMQ 0 as actions */
trtl_fw_mq_action_dispatch(TRTL_HMQ, 0); trtl_fw_mq_action_dispatch(TRTL_HMQ, 0);
...@@ -29,3 +19,15 @@ int main() ...@@ -29,3 +19,15 @@ int main()
return 0; return 0;
} }
struct trtl_fw_application app = {
.name = "hellofrm",
.version = {
.rt_id = CONFIG_RT_APPLICATION_ID,
.rt_version = RT_VERSION(0, 1),
.git_version = GIT_VERSION
},
.main = ping_main,
};
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment