Commit e392d7ad authored by Federico Vaga's avatar Federico Vaga

librt: add rt_init() function

It initializes the library and replace all the export functions. Now, you just
set up you application configuration and run rt_init().
Signed-off-by: Federico Vaga's avatarFederico Vaga <federico.vaga@cern.ch>
parent 13ea2f0d
...@@ -9,32 +9,12 @@ ...@@ -9,32 +9,12 @@
#include <errno.h> #include <errno.h>
#include <librt.h> #include <librt.h>
static action_t **rt_actions; /**< Exported actions */
static struct rt_variable *rt_variables; /**< Exported variables list */
static struct rt_structure *rt_structures; /**< Exported structures list */
static unsigned int rt_variables_count, rt_structures_count, rt_action_count;
const char *name = RT_APPLICATION_NAME;
const struct wrnc_rt_version version = {0, RT_APPLICATION_ID, 0, GIT_VERSION}; const struct wrnc_rt_version version = {0, RT_APPLICATION_ID, 0, GIT_VERSION};
struct rt_application *_app;
void rt_variable_export(struct rt_variable *variables, unsigned int count)
{
rt_variables_count = count;
rt_variables = variables;
}
void rt_structure_export(struct rt_structure *structures, unsigned int count)
{
rt_structures_count = count;
rt_structures = structures;
}
void rt_action_export(action_t **actions, unsigned int count)
{
rt_actions = actions;
rt_action_count = count;
}
/** /**
* it sets a structure coming from the host * it sets a structure coming from the host
*/ */
...@@ -52,18 +32,18 @@ int rt_structure_setter(struct wrnc_proto_header *hin, void *pin, ...@@ -52,18 +32,18 @@ int rt_structure_setter(struct wrnc_proto_header *hin, void *pin,
size = din[offset++]; size = din[offset++];
#ifdef LIBRT_DEBUG #ifdef LIBRT_DEBUG
pp_printf("%s Type %d Len %d Addr 0x%x\n", __func__, pp_printf("%s Type %d Len %d Addr 0x%x\n", __func__,
index, size, rt_structures[index].struct_ptr); index, size, _app->structures[index].struct_ptr);
delay(100000); delay(100000);
#endif #endif
if (rt_structures[index].len == size) { if (_app->structures[index].len == size) {
memcpy(rt_structures[index].struct_ptr, memcpy(_app->structures[index].struct_ptr,
&din[offset], size); &din[offset], size);
} }
#ifdef LIBRT_ERROR #ifdef LIBRT_ERROR
else { else {
pp_printf("%s:%d structure len not correct %d != %d\n", pp_printf("%s:%d structure len not correct %d != %d\n",
__func__, __LINE__, __func__, __LINE__,
rt_structures[index].len, size); _app->structures[index].len, size);
} }
#endif #endif
offset += (size / 4); /* Next TLV record */ offset += (size / 4); /* Next TLV record */
...@@ -95,17 +75,17 @@ int rt_structure_getter(struct wrnc_proto_header *hin, void *pin, ...@@ -95,17 +75,17 @@ int rt_structure_getter(struct wrnc_proto_header *hin, void *pin,
dout[offset++] = size; dout[offset++] = size;
#ifdef LIBRT_DEBUG #ifdef LIBRT_DEBUG
pp_printf("%s Type %d Len %d Addr 0x%x\n", __func__, pp_printf("%s Type %d Len %d Addr 0x%x\n", __func__,
index, size, rt_structures[index].struct_ptr); index, size, _app->structures[index].struct_ptr);
delay(100000); delay(100000);
#endif #endif
if (rt_structures[index].len == size) { if (_app->structures[index].len == size) {
memcpy(&dout[offset], rt_structures[index].struct_ptr, memcpy(&dout[offset], _app->structures[index].struct_ptr,
size); size);
} }
#ifdef LIBRT_ERROR #ifdef LIBRT_ERROR
else { else {
pp_printf("%s: structure len not correct %d != %d\n", pp_printf("%s: structure len not correct %d != %d\n",
__func__, rt_structures[index].len, size); __func__, _app->structures[index].len, size);
} }
#endif #endif
offset += (size / 4); /* Next TLV record */ offset += (size / 4); /* Next TLV record */
...@@ -150,9 +130,9 @@ int rt_variable_setter(struct wrnc_proto_header *hin, void *pin, ...@@ -150,9 +130,9 @@ int rt_variable_setter(struct wrnc_proto_header *hin, void *pin,
/* Write all values in the proper place */ /* Write all values in the proper place */
for (i = 0; i < hin->len; i += 2) { for (i = 0; i < hin->len; i += 2) {
if (din[i] >= rt_variables_count) if (din[i] >= _app->n_variables)
continue; continue;
var = &rt_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 & RT_VARIABLE_FLAG_WO) if (var->flags & RT_VARIABLE_FLAG_WO)
...@@ -163,7 +143,7 @@ int rt_variable_setter(struct wrnc_proto_header *hin, void *pin, ...@@ -163,7 +143,7 @@ int rt_variable_setter(struct wrnc_proto_header *hin, void *pin,
#ifdef LIBRT_DEBUG #ifdef LIBRT_DEBUG
pp_printf("%s index %d/%d | [0x%x] = 0x%08x <- 0x%08x (0x%08x) | index in msg (%d/%d)\n", pp_printf("%s index %d/%d | [0x%x] = 0x%08x <- 0x%08x (0x%08x) | index in msg (%d/%d)\n",
__func__, __func__,
din[i], rt_variables_count, din[i], _app->n_variables,
mem, *mem, val, din[i + 1], mem, *mem, val, din[i + 1],
i + 1, hin->len - 1); i + 1, hin->len - 1);
delay(100000); delay(100000);
...@@ -201,19 +181,19 @@ int rt_variable_getter(struct wrnc_proto_header *hin, void *pin, ...@@ -201,19 +181,19 @@ int rt_variable_getter(struct wrnc_proto_header *hin, void *pin,
/* Write all values in the proper place */ /* Write all values in the proper place */
for (i = 0; i < hout->len; i += 2) { for (i = 0; i < hout->len; i += 2) {
if (din[i] >= rt_variables_count) { 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 = &rt_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;
#ifdef LIBRT_DEBUG #ifdef LIBRT_DEBUG
pp_printf("%s index %d/%d | [0x%x] = 0x%08x -> 0x%08x | index in msg (%d/%d)\n", pp_printf("%s index %d/%d | [0x%x] = 0x%08x -> 0x%08x | index in msg (%d/%d)\n",
__func__, __func__,
dout[i], rt_variables_count, dout[i], _app->n_variables,
mem, *mem, dout[i + 1], mem, *mem, dout[i + 1],
i + 1, hin->len - 1); i + 1, hin->len - 1);
delay(100000); delay(100000);
...@@ -250,12 +230,12 @@ static inline int rt_action_run(struct wrnc_proto_header *hin, void *pin) ...@@ -250,12 +230,12 @@ static inline int rt_action_run(struct wrnc_proto_header *hin, void *pin)
void *pout; void *pout;
int err = 0; int err = 0;
if (hin->msg_id >= rt_action_count || !rt_actions[hin->msg_id]) { if (hin->msg_id >= _app->n_actions || !_app->actions[hin->msg_id]) {
pp_printf("Cannot dispatch ID 0x%x\n", hin->msg_id); pp_printf("Cannot dispatch ID 0x%x\n", hin->msg_id);
return -EINVAL; return -EINVAL;
} }
action = rt_actions[hin->msg_id]; action = _app->actions[hin->msg_id];
if (!(hin->flags & WRNC_PROTO_FLAG_SYNC)) { if (!(hin->flags & WRNC_PROTO_FLAG_SYNC)) {
/* Asynchronous message, then no output */ /* Asynchronous message, then no output */
...@@ -290,26 +270,25 @@ static inline int rt_action_run(struct wrnc_proto_header *hin, void *pin) ...@@ -290,26 +270,25 @@ static inline int rt_action_run(struct wrnc_proto_header *hin, void *pin)
/** /**
* It dispatch messages coming from a given HMQ slot * It dispatch messages coming from a given message queue.
* @param[in] mq_in_slot message queue to poll for incoming messages * @param[in] mq_in message queue index within mq declared in rt_application
* @param[in] is_remote 1 if we are usin a remote queue
* @todo provide support for remote queue * @todo provide support for remote queue
*/ */
int rt_mq_action_dispatch(unsigned int mq_in_slot, unsigned int is_remote) int rt_mq_action_dispatch(unsigned int mq_in)
{ {
#ifdef RTPERFORMANCE #ifdef RTPERFORMANCE
uint32_t sec, cyc, sec_n, cyc_n; uint32_t sec, cyc, sec_n, cyc_n;
#endif #endif
struct wrnc_proto_header *header; struct wrnc_proto_header *header;
uint32_t p; unsigned int mq_in_slot = _app->mq[mq_in].index;
unsigned int is_remote = _app->mq[mq_in].flags & RT_MQ_FLAGS_REMOTE;
struct rt_action *action; struct rt_action *action;
uint32_t *msg; uint32_t *msg;
void *pin; void *pin;
int err = 0; int err = 0;
/* HMQ control slot empty? */ /* HMQ control slot empty? */
p = mq_poll(); if (!(mq_poll() & ( 1 << mq_in_slot)))
if (!(p & ( 1 << mq_in_slot)))
return -EAGAIN; return -EAGAIN;
/* Get the message from the HMQ */ /* Get the message from the HMQ */
...@@ -358,3 +337,31 @@ void rt_get_time(uint32_t *seconds, uint32_t *cycles) ...@@ -358,3 +337,31 @@ void rt_get_time(uint32_t *seconds, uint32_t *cycles)
*seconds = lr_readl(WRN_CPU_LR_REG_TAI_SEC); *seconds = lr_readl(WRN_CPU_LR_REG_TAI_SEC);
*cycles = lr_readl(WRN_CPU_LR_REG_TAI_CYCLES); *cycles = lr_readl(WRN_CPU_LR_REG_TAI_CYCLES);
} }
/**
* Initialize the rt library for an optimal usage
*/
void rt_init(struct rt_application *app)
{
int i;
_app = app;
pp_printf("Running application '%s'\n", name);
if (version.fpga_id) {
pp_printf(" compatible only with FPGA '0x%x'\n",
version.fpga_id);
/* TODO get app id from FPGA and compare */
}
pp_printf(" application id '0x%x'\n", version.rt_id);
pp_printf(" application version '%d'\n", version.rt_version);
pp_printf(" source code id '0x%x'\n", version.git_version);
/* Purge all slots */
for (i = 0; i < _app->n_mq; ++i) {
mq_writel(!!(_app->mq[i].flags & RT_MQ_FLAGS_REMOTE),
MQ_CMD_PURGE,
MQ_OUT(_app->mq[i].index) + MQ_SLOT_COMMAND);
}
}
...@@ -18,6 +18,12 @@ ...@@ -18,6 +18,12 @@
#define RT_VARIABLE_FLAG_REG (1 << 0) #define RT_VARIABLE_FLAG_REG (1 << 0)
#define RT_MQ_FLAGS_REMOTE (1 << 0)
#define RT_MQ_FLAGS_OUTPUT (1 << 1)
#define RT_MQ_FLAGS_LOCAL (0)
#define RT_MQ_FLAGS_INPUT (0)
#ifdef LIBRT_DEBUG #ifdef LIBRT_DEBUG
static inline void rt_print_data(uint32_t *d, unsigned int count) static inline void rt_print_data(uint32_t *d, unsigned int count)
{ {
...@@ -64,8 +70,32 @@ struct rt_structure { ...@@ -64,8 +70,32 @@ struct rt_structure {
/* Maybe other option later in time */ /* Maybe other option later in time */
}; };
struct rt_mq {
uint8_t index;
unsigned long flags;
};
/**
* Real-Time Application Descriptor
*/
struct rt_application {
struct rt_mq *mq; /**< list of used MQ */
uint8_t n_mq; /**< number of available MQ */
struct rt_structure *structures; /**< exported structures */
unsigned int n_structures; /**< number or exported structures */
struct rt_variable *variables; /**< exported variables */
unsigned int n_variables; /**< number or exported variables */
action_t **actions;
unsigned int n_actions;
};
extern void rt_init(struct rt_application *app);
extern int rt_mq_register(struct rt_mq *mq, unsigned int n);
extern int rt_mq_action_register(uint32_t id, action_t action); extern int rt_mq_action_register(uint32_t id, action_t action);
extern int rt_mq_action_dispatch(unsigned int in_slot, unsigned int is_remote); extern int rt_mq_action_dispatch(unsigned int mq_in);
/** /**
...@@ -93,14 +123,10 @@ static inline void rt_send_nack(struct wrnc_proto_header *hin, void *pin, ...@@ -93,14 +123,10 @@ static inline void rt_send_nack(struct wrnc_proto_header *hin, void *pin,
extern void rt_get_time(uint32_t *seconds, uint32_t *cycles); extern void rt_get_time(uint32_t *seconds, uint32_t *cycles);
extern void rt_action_export(action_t **actions, unsigned int count); extern void rt_action_export(action_t **actions, unsigned int count);
extern void rt_variable_export(struct rt_variable *variable,
unsigned int count);
extern int rt_variable_setter(struct wrnc_proto_header *hin, void *pin, extern int rt_variable_setter(struct wrnc_proto_header *hin, void *pin,
struct wrnc_proto_header *hout, void *pout); struct wrnc_proto_header *hout, void *pout);
extern int rt_variable_getter(struct wrnc_proto_header *hin, void *pin, extern int rt_variable_getter(struct wrnc_proto_header *hin, void *pin,
struct wrnc_proto_header *hout, void *pout); struct wrnc_proto_header *hout, void *pout);
extern void rt_structure_export(struct rt_structure *structures,
unsigned int count);
extern int rt_structure_setter(struct wrnc_proto_header *hin, void *pin, extern int rt_structure_setter(struct wrnc_proto_header *hin, void *pin,
struct wrnc_proto_header *hout, void *pout); struct wrnc_proto_header *hout, void *pout);
extern int rt_structure_getter(struct wrnc_proto_header *hin, void *pin, extern int rt_structure_getter(struct wrnc_proto_header *hin, void *pin,
......
...@@ -7,6 +7,7 @@ EXTRA_CFLAGS += -I../common ...@@ -7,6 +7,7 @@ EXTRA_CFLAGS += -I../common
EXTRA_CFLAGS += -D__MAX_ACTION_RECV=0 EXTRA_CFLAGS += -D__MAX_ACTION_RECV=0
EXTRA_CFLAGS += -D__MAX_ACTION_SEND=0 EXTRA_CFLAGS += -D__MAX_ACTION_SEND=0
EXTRA_CFLAGS += -DRTPERFORMANCE EXTRA_CFLAGS += -DRTPERFORMANCE
EXTRA_CFLAGS += -DRT_APPLICATION_NAME="\"svec-demo\""
EXTRA_CFLAGS += -DFPGA_APPLICATION_ID=0xd330d330 EXTRA_CFLAGS += -DFPGA_APPLICATION_ID=0xd330d330
EXTRA_CFLAGS += -DRT_APPLICATION_ID=0xdeadbeef EXTRA_CFLAGS += -DRT_APPLICATION_ID=0xdeadbeef
EXTRA_CFLAGS += -DLIBRT_DEBUG -DLIBRT_ERROR EXTRA_CFLAGS += -DLIBRT_DEBUG -DLIBRT_ERROR
......
...@@ -17,6 +17,23 @@ ...@@ -17,6 +17,23 @@
#define GPIO_DDR 0x8 /* Direction Data Register */ #define GPIO_DDR 0x8 /* Direction Data Register */
#define GPIO_PSR 0xC /* Status Register */ #define GPIO_PSR 0xC /* Status Register */
enum rt_slot_name {
DEMO_CMD_IN = 0,
DEMO_CMD_OUT,
};
struct rt_mq mq[] = {
[DEMO_CMD_IN] = {
.index = 0,
.flags = RT_MQ_FLAGS_LOCAL | RT_MQ_FLAGS_INPUT,
},
[DEMO_CMD_OUT] = {
.index = 0,
.flags = RT_MQ_FLAGS_LOCAL | RT_MQ_FLAGS_OUTPUT,
},
};
static uint32_t out_seq = 0; static uint32_t out_seq = 0;
static struct demo_structure demo_struct; static struct demo_structure demo_struct;
...@@ -79,6 +96,21 @@ static action_t *demo_actions[] = { ...@@ -79,6 +96,21 @@ static action_t *demo_actions[] = {
[RT_ACTION_RECV_STRUCT_GET] = rt_structure_getter, [RT_ACTION_RECV_STRUCT_GET] = rt_structure_getter,
}; };
struct rt_application app = {
.mq = mq,
.n_mq = 2,
.structures = demo_structures,
.n_structures = __DEMO_STRUCT_MAX,
.variables = demo_variables,
.n_variables = __DEMO_VAR_MAX,
.actions = demo_actions,
.n_actions = 128, /* FIXME replace 128 with correct number */
};
/** /**
* It sends messages over the debug interface * It sends messages over the debug interface
*/ */
...@@ -95,18 +127,13 @@ static void demo_debug_interface(void) ...@@ -95,18 +127,13 @@ static void demo_debug_interface(void)
*/ */
int main() int main()
{ {
rt_init(&app);
demo_debug_interface(); demo_debug_interface();
/* Export a set of variables */
rt_variable_export(demo_variables, __DEMO_VAR_MAX);
rt_structure_export(demo_structures, __DEMO_STRUCT_MAX);
rt_action_export(demo_actions, 128); /* FIXME replace 128 with correct number */
while (1) { while (1) {
/* Handle all messages incoming from slot DEMO_HMQ_IN /* Handle all messages incoming from slot DEMO_HMQ_IN
as actions */ as actions */
rt_mq_action_dispatch(DEMO_HMQ_IN, 0); rt_mq_action_dispatch(DEMO_CMD_IN);
} }
return 0; return 0;
......
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