tdc stuff
This commit is contained in:
parent
d74bef5e61
commit
9b703ef0a9
@ -23,6 +23,8 @@ uint32_t fifo_txpdc(struct fifo *fifo, AT91S_PDC *pdc, uint16_t maxsize);
|
|||||||
uint32_t fifo_putbyte(struct fifo *fifo, char c);
|
uint32_t fifo_putbyte(struct fifo *fifo, char c);
|
||||||
uint32_t fifo_getbyte(struct fifo *fifo, char *p);
|
uint32_t fifo_getbyte(struct fifo *fifo, char *p);
|
||||||
|
|
||||||
|
char * fifo_peek(struct fifo *fifo, uint32_t len);
|
||||||
|
|
||||||
struct fifo * fifo_alloc(uint32_t size);
|
struct fifo * fifo_alloc(uint32_t size);
|
||||||
|
|
||||||
#endif /*FIFO_H_*/
|
#endif /*FIFO_H_*/
|
||||||
|
@ -48,7 +48,7 @@ struct tdc_getvars_reply {
|
|||||||
uint8_t size;
|
uint8_t size;
|
||||||
uint8_t id; // variable ID (max 256 vars / board)
|
uint8_t id; // variable ID (max 256 vars / board)
|
||||||
uint32_t flags; // variable parameters (type, size, ro/rw)
|
uint32_t flags; // variable parameters (type, size, ro/rw)
|
||||||
uint8_t name[0]; // variable name, excluding '\0'
|
char name[0]; // variable name, excluding '\0'
|
||||||
} __attribute__ ((packed));
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
struct tdc_getvalue_request {
|
struct tdc_getvalue_request {
|
||||||
@ -87,8 +87,8 @@ struct tdc_reqvalues_reply {
|
|||||||
|
|
||||||
|
|
||||||
struct tdc_value {
|
struct tdc_value {
|
||||||
const void *ptr;
|
void *data;
|
||||||
const uint8_t *name;
|
const char *name;
|
||||||
uint32_t flags;
|
uint32_t flags;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
15
src/fifo.c
15
src/fifo.c
@ -16,6 +16,7 @@
|
|||||||
* Free Software Foundation, Inc., *
|
* Free Software Foundation, Inc., *
|
||||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
#include <stdio.h>
|
||||||
#include "AT91SAM7S256.h"
|
#include "AT91SAM7S256.h"
|
||||||
#include "atomic.h"
|
#include "atomic.h"
|
||||||
#include "fifo.h"
|
#include "fifo.h"
|
||||||
@ -45,6 +46,7 @@ static uint32_t fifo_used(struct fifo *fifo)
|
|||||||
uint32_t fifo_put(struct fifo *fifo, const char *buf, uint32_t len)
|
uint32_t fifo_put(struct fifo *fifo, const char *buf, uint32_t len)
|
||||||
{
|
{
|
||||||
uint32_t left = fifo->size - fifo_used(fifo);
|
uint32_t left = fifo->size - fifo_used(fifo);
|
||||||
|
// TODO: check semantic
|
||||||
if (len > left)
|
if (len > left)
|
||||||
len = left;
|
len = left;
|
||||||
|
|
||||||
@ -72,6 +74,19 @@ uint32_t fifo_get(struct fifo *fifo, char *buf, uint32_t len)
|
|||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* returns a pointer to the data in the fifo
|
||||||
|
* (without changing internal state)
|
||||||
|
*/
|
||||||
|
char * fifo_peek(struct fifo *fifo, uint32_t len)
|
||||||
|
{
|
||||||
|
uint32_t used = fifo_used(fifo);
|
||||||
|
if (len > used)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return fifo->buf + (fifo->out & FIFO_MASK(fifo));
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* receive data via PDC and put it into fifo
|
* receive data via PDC and put it into fifo
|
||||||
*/
|
*/
|
||||||
|
152
src/telemetrie.c
152
src/telemetrie.c
@ -27,12 +27,18 @@
|
|||||||
extern struct tdc_value _tdc_value_table;
|
extern struct tdc_value _tdc_value_table;
|
||||||
extern struct tdc_value _tdc_value_table_end;
|
extern struct tdc_value _tdc_value_table_end;
|
||||||
|
|
||||||
typedef uint32_t (txfunc_t)(const uint8_t *data, uint32_t size);
|
/*
|
||||||
|
* transmit function
|
||||||
|
* returns:
|
||||||
|
* -1 : could not sent data (e.g. fifo full)
|
||||||
|
* >= 0 : bytes sent
|
||||||
|
*/
|
||||||
|
typedef uint32_t (txfunc_t)(struct tdc_pkt_header *head);
|
||||||
|
|
||||||
/* just eat the packet */
|
/* just eat the packet */
|
||||||
static uint32_t txdummy(const uint8_t *data, uint32_t size)
|
static uint32_t txdummy(struct tdc_pkt_header *head)
|
||||||
{
|
{
|
||||||
return -1;
|
return head->size;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* table of txfuncs for routing/forwarding */
|
/* table of txfuncs for routing/forwarding */
|
||||||
@ -53,88 +59,84 @@ void tdc_register_txfunc(uint32_t addr, txfunc_t *txfunc)
|
|||||||
transmit_table[addr] = txfunc;
|
transmit_table[addr] = txfunc;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t tdc_transmit(uint32_t addr, const uint8_t *data, uint32_t size)
|
int32_t tdc_transmit(uint32_t addr, struct tdc_pkt_header *head)
|
||||||
{
|
{
|
||||||
if (addr <= ARRAY_SIZE(transmit_table))
|
if (addr <= ARRAY_SIZE(transmit_table))
|
||||||
return transmit_table[addr](data, size);
|
return transmit_table[addr](head);
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
void *blub = NULL;
|
* send all variable names & flags
|
||||||
func(&blub);
|
* returns:
|
||||||
*/
|
* 0 - success (*id = 0)
|
||||||
int32_t tdc_get_vars(void **privdata)
|
* -1 - not all data was sent, restart request later (*id has restart-point)
|
||||||
|
*/
|
||||||
|
int32_t tdc_get_vars(uint32_t *id)
|
||||||
{
|
{
|
||||||
struct tdc_value **value = (struct tdc_value **)privdata;
|
struct tdc_value *value = &_tdc_value_table + *id;
|
||||||
|
|
||||||
if (*value == NULL)
|
while (value < &_tdc_value_table_end) {
|
||||||
*value = &_tdc_value_table;
|
uint32_t datalen = strlen(value->name);
|
||||||
|
|
||||||
uint32_t id = (*value - &_tdc_value_table) / sizeof(struct tdc_value);
|
|
||||||
|
|
||||||
while (*value < &_tdc_value_table_end) {
|
|
||||||
uint32_t datalen = strlen((*value)->name);
|
|
||||||
|
|
||||||
struct tdc_getvars_reply *reply = alloc(sizeof(struct tdc_getvars_reply) + datalen);
|
struct tdc_getvars_reply *reply = alloc(sizeof(struct tdc_getvars_reply) + datalen);
|
||||||
reply->cmd = TDC_REPLY | TDC_ADDR1 | TDC_GETVARS;
|
reply->cmd = TDC_REPLY | TDC_ADDR1 | TDC_GETVARS;
|
||||||
reply->size = sizeof(struct tdc_getvars_reply) + datalen;
|
reply->size = sizeof(struct tdc_getvars_reply) + datalen;
|
||||||
reply->id = id;
|
reply->id = *id;
|
||||||
reply->flags = (*value)->flags;
|
reply->flags = value->flags;
|
||||||
memcpy(reply->name, (*value)->name, datalen);
|
memcpy(reply->name, value->name, datalen);
|
||||||
|
|
||||||
int32_t ret = transmit_table[TDC_ADDR0]((const uint8_t *)reply, reply->size);
|
uint32_t txerror = (tdc_transmit(TDC_ADDR0, ((struct tdc_pkt_header *)reply)) != reply->size);
|
||||||
free(reply);
|
free(reply);
|
||||||
|
|
||||||
if (ret != reply->size)
|
/* transmit fifo is full, remember position (*id) and restart */
|
||||||
|
if (txerror)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
id++;
|
(*id)++;
|
||||||
(*value)++;
|
value++;
|
||||||
}
|
}
|
||||||
|
*id = 0;
|
||||||
/* TODO: all done */
|
|
||||||
(*value) = NULL;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
int32_t tdc_get_value(uint32_t id)
|
||||||
|
|
||||||
static int32_t tdc_get_values(uint8_t *buf, uint32_t size, void **key)
|
|
||||||
{
|
{
|
||||||
if (*key == NULL)
|
struct tdc_value *value = &_tdc_value_table + id;
|
||||||
*key = &_tdc_value_table;
|
uint32_t datalen = value->flags & TDC_SIZEMASK;
|
||||||
|
|
||||||
uint32_t id = (*key - &_tdc_value_table) / sizeof(struct tdc_value);
|
struct tdc_getvalue_reply *reply = alloc(sizeof(struct tdc_getvalue_reply) + datalen);
|
||||||
uint32_t pos = 0;
|
reply->cmd = TDC_REPLY | TDC_ADDR1 | TDC_GETVALUE;
|
||||||
|
reply->size = sizeof(struct tdc_getvars_reply) + datalen;
|
||||||
|
reply->id = id;
|
||||||
|
memcpy(reply->data, value->data, datalen);
|
||||||
|
|
||||||
while (*key < &_tdc_value_table_end) {
|
int32_t txerror = (tdc_transmit(TDC_ADDR0, ((struct tdc_pkt_header *)reply)) != reply->size);
|
||||||
struct tdc_value *tmp = (struct tdc_value *)*key;
|
free(reply);
|
||||||
uint32_t datalen = (tmp->flags & TDC_SIZEMASK);
|
|
||||||
|
|
||||||
/* fits in buffer? */
|
return (txerror) ? -1 : 0;
|
||||||
if ((size - pos) < (2 + 1 + datalen))
|
}
|
||||||
return (pos > 0) ? pos : -1;
|
|
||||||
|
void tdc_set_value(uint32_t id, uint8_t *data)
|
||||||
buf[pos++] = TDC_VALUEOP;
|
{
|
||||||
buf[pos++] = 1 + datalen;
|
struct tdc_value *value = &_tdc_value_table + id;
|
||||||
buf[pos++] = id++;
|
uint32_t datalen = value->flags & TDC_SIZEMASK;
|
||||||
|
|
||||||
memcpy(buf + pos, tmp->ptr, datalen);
|
// TODO: atomic?
|
||||||
pos += datalen;
|
memcpy(value->data, data, datalen);
|
||||||
|
|
||||||
*key += sizeof(struct tdc_value);
|
|
||||||
}
|
|
||||||
return pos;
|
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* parses tdc data
|
* parses tdc data
|
||||||
|
* returns:
|
||||||
|
* -1 : data too short / error
|
||||||
|
* >= 0 : data read, come back if there is more
|
||||||
*/
|
*/
|
||||||
int32_t tdc_parse_pkt(txfunc_t *txfunc, const uint8_t *data, uint32_t size)
|
int32_t tdc_parse_pkt(txfunc_t *txfunc, const uint8_t *data, uint32_t size)
|
||||||
{
|
{
|
||||||
|
// TODO: use a fifo, with a peek function?
|
||||||
|
|
||||||
struct tdc_pkt_header *head = (struct tdc_pkt_header *)data;
|
struct tdc_pkt_header *head = (struct tdc_pkt_header *)data;
|
||||||
|
|
||||||
if (size < sizeof(struct tdc_pkt_header))
|
if (size < sizeof(struct tdc_pkt_header))
|
||||||
@ -142,41 +144,55 @@ int32_t tdc_parse_pkt(txfunc_t *txfunc, const uint8_t *data, uint32_t size)
|
|||||||
|
|
||||||
/* if it's a hello-request, remember the txfunc as path to the host */
|
/* if it's a hello-request, remember the txfunc as path to the host */
|
||||||
if ((head->cmd & (TDC_OPCODEMASK & TDC_DIR)) == TDC_HELLO)
|
if ((head->cmd & (TDC_OPCODEMASK & TDC_DIR)) == TDC_HELLO)
|
||||||
transmit_table[TDC_ADDR0] = txfunc;
|
tdc_register_txfunc(TDC_ADDR0, txfunc);
|
||||||
|
|
||||||
/* all replys go to the HOST */
|
/* all replys go to the HOST */
|
||||||
if (head->cmd & TDC_REPLY) {
|
if (head->cmd & TDC_REPLY) {
|
||||||
return transmit_table[TDC_ADDR0](data, head->size);
|
// TODO: wrong returncode
|
||||||
|
return tdc_transmit(TDC_ADDR0, head);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* forward this packet? */
|
/* forward this packet? */
|
||||||
if ((head->cmd & TDC_ADDRMASK) != TDC_ADDR1) {
|
if ((head->cmd & TDC_ADDRMASK) != TDC_ADDR1) {
|
||||||
uint32_t addr = (head->cmd & TDC_ADDRMASK) >> 4;
|
uint32_t addr = (head->cmd & TDC_ADDRMASK) >> 4;
|
||||||
return transmit_table[addr](data, head->size);
|
// TODO: wrong returncode
|
||||||
|
return tdc_transmit(addr, head);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* parse the packet */
|
/* parse the packet */
|
||||||
switch (head->cmd & TDC_OPCODEMASK) {
|
switch (head->cmd & TDC_OPCODEMASK) {
|
||||||
/* HELLO from HOST */
|
/* HELLO from HOST */
|
||||||
case TDC_HELLO:
|
case TDC_HELLO:
|
||||||
transmit_table[TDC_ADDR0]((const uint8_t *)&hello_reply, sizeof(hello_reply));
|
tdc_transmit(TDC_ADDR0, (struct tdc_pkt_header *)&hello_reply);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TDC_GETVARS:
|
case TDC_GETVARS: {
|
||||||
// TODO: exec func
|
static uint32_t i;
|
||||||
break;
|
|
||||||
|
|
||||||
case TDC_GETVALUE:
|
/* tx-fifo is full, complete request later */
|
||||||
// TODO: exec func
|
if (tdc_get_vars(&i) == -1)
|
||||||
break;
|
return 0;
|
||||||
|
|
||||||
case TDC_SETVALUE:
|
} break;
|
||||||
// TODO: exec func
|
|
||||||
break;
|
|
||||||
|
|
||||||
case TDC_REQVALUES:
|
case TDC_GETVALUE: {
|
||||||
// TODO: exec func
|
struct tdc_getvalue_request *pkt = (struct tdc_getvalue_request *)data;
|
||||||
break;
|
|
||||||
|
/* tx-fifo is full, retry request later */
|
||||||
|
if (tdc_get_value(pkt->id) == -1)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case TDC_SETVALUE: {
|
||||||
|
struct tdc_setvalue_request *pkt = (struct tdc_setvalue_request *)data;
|
||||||
|
tdc_set_value(pkt->id, pkt->data);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case TDC_REQVALUES: {
|
||||||
|
struct tdc_reqvalues_request *pkt = (struct tdc_reqvalues_request *)data;
|
||||||
|
|
||||||
|
} break;
|
||||||
|
|
||||||
case TDC_TERMINAL:
|
case TDC_TERMINAL:
|
||||||
// TODO: not possible?
|
// TODO: not possible?
|
||||||
|
Loading…
Reference in New Issue
Block a user