save failed integration state
This commit is contained in:
418
gomspace/libparam_client/src/pp/cmd/master_cmd.c
Normal file
418
gomspace/libparam_client/src/pp/cmd/master_cmd.c
Normal file
@ -0,0 +1,418 @@
|
||||
/* Copyright (c) 2013-2017 GomSpace A/S. All rights reserved. */
|
||||
|
||||
#include <gs/param/pp/spi/spi.h>
|
||||
#include <gs/param/pp/i2c/i2c.h>
|
||||
#include <gs/util/gosh/command.h>
|
||||
#include <gs/util/stdio.h>
|
||||
#include <gs/util/string.h>
|
||||
#include <gs/util/log.h>
|
||||
|
||||
static bool use_checksum;
|
||||
|
||||
static gs_pp_t gs_pp;
|
||||
|
||||
static int cmd_spi_init(gs_command_context_t *ctx)
|
||||
{
|
||||
uint8_t slave;
|
||||
gs_error_t error = gs_string_to_uint8(ctx->argv[1], &slave);
|
||||
if (error) {
|
||||
return error;
|
||||
}
|
||||
|
||||
bool big_endian = false;
|
||||
if (ctx->argc > 2) {
|
||||
error = gs_string_to_bool(ctx->argv[2], &big_endian);
|
||||
if (error) {
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
error = gs_pp_spi_init(&gs_pp, slave, big_endian);
|
||||
if (error) {
|
||||
memset(&gs_pp, 0, sizeof(gs_pp));
|
||||
return error;
|
||||
}
|
||||
|
||||
return GS_OK;
|
||||
}
|
||||
|
||||
static int cmd_i2c_init(gs_command_context_t *ctx)
|
||||
{
|
||||
uint8_t bus;
|
||||
gs_error_t error = gs_string_to_uint8(ctx->argv[1], &bus);
|
||||
if (error) {
|
||||
return GS_ERROR_ARG;
|
||||
}
|
||||
|
||||
uint8_t addr;
|
||||
error = gs_string_to_uint8(ctx->argv[2], &addr);
|
||||
if (error) {
|
||||
return GS_ERROR_ARG;
|
||||
}
|
||||
|
||||
bool big_endian = false;
|
||||
if (ctx->argc > 3) {
|
||||
error = gs_string_to_bool(ctx->argv[3], &big_endian);
|
||||
if (error) {
|
||||
return GS_ERROR_ARG;
|
||||
}
|
||||
}
|
||||
|
||||
error = gs_pp_i2c_init(&gs_pp, bus, addr, big_endian);
|
||||
if (error) {
|
||||
memset(&gs_pp, 0, sizeof(gs_pp));
|
||||
return error;
|
||||
}
|
||||
|
||||
return GS_OK;
|
||||
}
|
||||
|
||||
static int cmd_checksum(gs_command_context_t *ctx)
|
||||
{
|
||||
if (ctx->argc > 1) {
|
||||
if (gs_string_to_bool(ctx->argv[1], &use_checksum)) {
|
||||
return GS_ERROR_ARG;
|
||||
}
|
||||
}
|
||||
printf("Use CHECKSUM: %d\r\n", use_checksum);
|
||||
return GS_OK;
|
||||
}
|
||||
|
||||
// get_xxxx <table> <addr>
|
||||
static int cmd_parse(gs_command_context_t *ctx,
|
||||
uint32_t * table, uint32_t * addr)
|
||||
{
|
||||
if (ctx->argc < 3) {
|
||||
return GS_ERROR_ARG;
|
||||
}
|
||||
|
||||
gs_error_t error = gs_string_to_uint32(ctx->argv[1], table);
|
||||
if (error || (*table > 7)) {
|
||||
return GS_ERROR_ARG;
|
||||
}
|
||||
|
||||
error = gs_string_to_uint32(ctx->argv[2], addr);
|
||||
if (error || (*addr > 255)) {
|
||||
return GS_ERROR_ARG;
|
||||
}
|
||||
|
||||
return GS_OK;
|
||||
}
|
||||
|
||||
static int cmd_get_parse(gs_command_context_t * ctx,
|
||||
uint32_t * table, uint32_t * addr, uint32_t * count)
|
||||
{
|
||||
int res = cmd_parse(ctx, table, addr);
|
||||
if (res == GS_OK) {
|
||||
*count = 1;
|
||||
if (ctx->argc > 3) {
|
||||
gs_error_t error = gs_string_to_uint32(ctx->argv[3], count);
|
||||
if (error || (*count > 100)) {
|
||||
return GS_ERROR_ARG;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
#define CMD_GET(_ctx, _type, _func, _format) \
|
||||
{ \
|
||||
uint32_t table; \
|
||||
uint32_t addr; \
|
||||
uint32_t count; \
|
||||
int res = cmd_get_parse(_ctx, &table, &addr, &count); \
|
||||
if (res == GS_OK) { \
|
||||
_type value[count]; \
|
||||
gs_error_t error = _func(&gs_pp, table, addr, value, count, use_checksum ? GS_PP_FLAG_CHECKSUM : 0); \
|
||||
if (error) { \
|
||||
return error; \
|
||||
} \
|
||||
printf("value(s): "); \
|
||||
for (unsigned int i = 0; i < count; ++i) { \
|
||||
printf("%" _format " ", value[i]); \
|
||||
} \
|
||||
printf("\r\n"); \
|
||||
} \
|
||||
return res; \
|
||||
}
|
||||
|
||||
static int cmd_get_int8(gs_command_context_t * ctx)
|
||||
{
|
||||
CMD_GET(ctx, int8_t, gs_pp_get_int8, PRId8);
|
||||
}
|
||||
|
||||
static int cmd_get_int16(gs_command_context_t * ctx)
|
||||
{
|
||||
CMD_GET(ctx, int16_t, gs_pp_get_int16, PRId16);
|
||||
}
|
||||
|
||||
static int cmd_get_int32(gs_command_context_t * ctx)
|
||||
{
|
||||
CMD_GET(ctx, int32_t, gs_pp_get_int32, PRId32);
|
||||
}
|
||||
|
||||
static int cmd_get_uint8(gs_command_context_t * ctx)
|
||||
{
|
||||
CMD_GET(ctx, uint8_t, gs_pp_get_uint8, PRIu8);
|
||||
}
|
||||
|
||||
static int cmd_get_uint16(gs_command_context_t * ctx)
|
||||
{
|
||||
CMD_GET(ctx, uint16_t, gs_pp_get_uint16, PRIu16);
|
||||
}
|
||||
|
||||
static int cmd_get_uint32(gs_command_context_t * ctx)
|
||||
{
|
||||
CMD_GET(ctx, uint32_t, gs_pp_get_uint32, PRIu32);
|
||||
}
|
||||
|
||||
static int cmd_get_float(gs_command_context_t * ctx)
|
||||
{
|
||||
CMD_GET(ctx, float, gs_pp_get_float, "f");
|
||||
}
|
||||
|
||||
#define CMD_SET(_ctx, _type, _func, _convert) \
|
||||
{ \
|
||||
const unsigned int MAX_VALUES = 20; \
|
||||
uint32_t table; \
|
||||
uint32_t addr; \
|
||||
int res = cmd_parse(_ctx, &table, &addr); \
|
||||
if (res == GS_OK) { \
|
||||
_type value[MAX_VALUES]; \
|
||||
unsigned int count = 0; \
|
||||
for (int i = 3; (i < _ctx->argc) && (count < MAX_VALUES); ++i, ++count) { \
|
||||
res = _convert(_ctx->argv[i], &value[count]); \
|
||||
if (res) { \
|
||||
return GS_ERROR_DATA; \
|
||||
} \
|
||||
} \
|
||||
res = _func(&gs_pp, table, addr, value, count, use_checksum ? GS_PP_FLAG_CHECKSUM : 0); \
|
||||
} \
|
||||
return res; \
|
||||
}
|
||||
|
||||
static int cmd_set_int8(gs_command_context_t * ctx)
|
||||
{
|
||||
CMD_SET(ctx, int8_t, gs_pp_set_int8, gs_string_to_int8);
|
||||
}
|
||||
|
||||
static int cmd_set_int16(gs_command_context_t * ctx)
|
||||
{
|
||||
CMD_SET(ctx, int16_t, gs_pp_set_int16, gs_string_to_int16);
|
||||
}
|
||||
|
||||
static int cmd_set_int32(gs_command_context_t * ctx)
|
||||
{
|
||||
CMD_SET(ctx, int32_t, gs_pp_set_int32, gs_string_to_int32);
|
||||
}
|
||||
|
||||
static int cmd_set_uint8(gs_command_context_t * ctx)
|
||||
{
|
||||
CMD_SET(ctx, uint8_t, gs_pp_set_uint8, gs_string_to_uint8);
|
||||
}
|
||||
|
||||
static int cmd_set_uint16(gs_command_context_t * ctx)
|
||||
{
|
||||
CMD_SET(ctx, uint16_t, gs_pp_set_uint16, gs_string_to_uint16);
|
||||
}
|
||||
|
||||
static int cmd_set_uint32(gs_command_context_t * ctx)
|
||||
{
|
||||
CMD_SET(ctx, uint32_t, gs_pp_set_uint32, gs_string_to_uint32);
|
||||
}
|
||||
|
||||
static int cmd_set_float(gs_command_context_t * ctx)
|
||||
{
|
||||
CMD_SET(ctx, float, gs_pp_set_float, gs_string_to_float);
|
||||
}
|
||||
|
||||
static int cmd_get_table_lock(gs_command_context_t * ctx)
|
||||
{
|
||||
uint32_t table;
|
||||
gs_error_t res = gs_string_to_uint32(ctx->argv[1], &table);
|
||||
if (res == GS_OK) {
|
||||
if (table <= 7) {
|
||||
bool lock;
|
||||
res = gs_pp_get_table_lock(&gs_pp, table, &lock, GS_PP_FLAG_CHECKSUM);
|
||||
if (res == GS_OK) {
|
||||
const char locked[] = "locked\n";
|
||||
const char unlocked[] = "unlocked\n";
|
||||
const char * lock_state = (lock) ? locked : unlocked;
|
||||
printf("Table %s", lock_state);
|
||||
}
|
||||
} else {
|
||||
res = GS_ERROR_ARG;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static int cmd_set_table_lock(gs_command_context_t * ctx)
|
||||
{
|
||||
uint32_t table;
|
||||
gs_error_t res = gs_string_to_uint32(ctx->argv[1], &table);
|
||||
if (res == GS_OK) {
|
||||
if (table <= 7) {
|
||||
uint32_t lock;
|
||||
res = gs_string_to_uint32(ctx->argv[2], &lock);
|
||||
if (res == GS_OK) {
|
||||
if(lock <= 1) {
|
||||
res = gs_pp_set_table_lock(&gs_pp, table, (bool *)&lock, GS_PP_FLAG_CHECKSUM);
|
||||
} else {
|
||||
res = GS_ERROR_ARG;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
res = GS_ERROR_ARG;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static const gs_command_t gs_param_cmd_master_pp_sub[] = {
|
||||
{
|
||||
.name = "spi_init",
|
||||
.help = "Initialize/setup SPI device",
|
||||
.usage = "<slave> [big_endian]",
|
||||
.handler = cmd_spi_init,
|
||||
.mandatory_args = 1,
|
||||
.optional_args = 1,
|
||||
},{
|
||||
.name = "i2c_init",
|
||||
.help = "Initialize/setup I2C device",
|
||||
.usage = "<device> <addr> [big_endian]",
|
||||
.handler = cmd_i2c_init,
|
||||
.mandatory_args = 2,
|
||||
.optional_args = 1,
|
||||
},{
|
||||
.name = "checksum",
|
||||
.help = "Enable/disable checksum",
|
||||
.usage = "[0|1]",
|
||||
.handler = cmd_checksum,
|
||||
.optional_args = 1,
|
||||
},{
|
||||
.name = "get_table_lock",
|
||||
.help = "Get table lock (0 = unlocked, 1 = locked)",
|
||||
.usage = "<table>",
|
||||
.mandatory_args = 1,
|
||||
.handler = cmd_get_table_lock,
|
||||
},{
|
||||
.name = "set_table_lock",
|
||||
.help = "Set table lock (0 = unlocked, 1 = locked)",
|
||||
.usage = "<table> <lock/unlock>",
|
||||
.mandatory_args = 2,
|
||||
.handler = cmd_set_table_lock,
|
||||
},{
|
||||
.name = "get_int8",
|
||||
.help = "Get int8",
|
||||
.usage = "<table> <addr> [count]",
|
||||
.handler = cmd_get_int8,
|
||||
.mandatory_args = 2,
|
||||
.optional_args = 1,
|
||||
},{
|
||||
.name = "get_int16",
|
||||
.help = "Get int16",
|
||||
.usage = "<table> <addr> [count]",
|
||||
.handler = cmd_get_int16,
|
||||
.mandatory_args = 2,
|
||||
.optional_args = 1,
|
||||
},{
|
||||
.name = "get_int32",
|
||||
.help = "Get int32",
|
||||
.usage = "<table> <addr> [count]",
|
||||
.handler = cmd_get_int32,
|
||||
.mandatory_args = 2,
|
||||
.optional_args = 1,
|
||||
},{
|
||||
.name = "get_uint8",
|
||||
.help = "Get uint8",
|
||||
.usage = "<table> <addr> [count]",
|
||||
.handler = cmd_get_uint8,
|
||||
.mandatory_args = 2,
|
||||
.optional_args = 1,
|
||||
},{
|
||||
.name = "get_uint16",
|
||||
.help = "Get uint16",
|
||||
.usage = "<table> <addr> [count]",
|
||||
.handler = cmd_get_uint16,
|
||||
.mandatory_args = 2,
|
||||
.optional_args = 1,
|
||||
},{
|
||||
.name = "get_uint32",
|
||||
.help = "Get uint32",
|
||||
.usage = "<table> <addr> [count]",
|
||||
.handler = cmd_get_uint32,
|
||||
.mandatory_args = 2,
|
||||
.optional_args = 1,
|
||||
},{
|
||||
.name = "get_float",
|
||||
.help = "Get float",
|
||||
.usage = "<table> <addr> [count]",
|
||||
.handler = cmd_get_float,
|
||||
.mandatory_args = 2,
|
||||
.optional_args = 1,
|
||||
},{
|
||||
.name = "set_int8",
|
||||
.help = "Set int8",
|
||||
.usage = "<table> <addr> <data> [data] ...",
|
||||
.handler = cmd_set_int8,
|
||||
.mandatory_args = 3,
|
||||
.optional_args = 20,
|
||||
},{
|
||||
.name = "set_int16",
|
||||
.help = "Set int16",
|
||||
.usage = "<table> <addr> <data> [data] ...",
|
||||
.handler = cmd_set_int16,
|
||||
.mandatory_args = 3,
|
||||
.optional_args = 20,
|
||||
},{
|
||||
.name = "set_int32",
|
||||
.help = "Set int32",
|
||||
.usage = "<table> <addr> <data> [data] ...",
|
||||
.handler = cmd_set_int32,
|
||||
.mandatory_args = 3,
|
||||
.optional_args = 20,
|
||||
},{
|
||||
.name = "set_uint8",
|
||||
.help = "Set uint8",
|
||||
.usage = "<table> <addr> <data> [data] ...",
|
||||
.handler = cmd_set_uint8,
|
||||
.mandatory_args = 3,
|
||||
.optional_args = 20,
|
||||
},{
|
||||
.name = "set_uint16",
|
||||
.help = "Set uint16",
|
||||
.usage = "<table> <addr> <data> [data] ...",
|
||||
.handler = cmd_set_uint16,
|
||||
.mandatory_args = 3,
|
||||
.optional_args = 20,
|
||||
},{
|
||||
.name = "set_uint32",
|
||||
.help = "Set uint32",
|
||||
.usage = "<table> <addr> <data> [data] ...",
|
||||
.handler = cmd_set_uint32,
|
||||
.mandatory_args = 3,
|
||||
.optional_args = 20,
|
||||
},{
|
||||
.name = "set_float",
|
||||
.help = "Set float",
|
||||
.usage = "<table> <addr> <data> [data] ...",
|
||||
.handler = cmd_set_float,
|
||||
.mandatory_args = 3,
|
||||
.optional_args = 20,
|
||||
}
|
||||
};
|
||||
|
||||
static const gs_command_t GS_COMMAND_ROOT gs_param_cmd_master_pp[] = {
|
||||
{
|
||||
.name = "pp",
|
||||
.help = "Param Protocol interface",
|
||||
.chain = GS_COMMAND_INIT_CHAIN(gs_param_cmd_master_pp_sub),
|
||||
}
|
||||
};
|
||||
|
||||
gs_error_t gs_pp_register_commands(void)
|
||||
{
|
||||
return GS_COMMAND_REGISTER(gs_param_cmd_master_pp);
|
||||
}
|
129
gomspace/libparam_client/src/pp/i2c/i2c.c
Normal file
129
gomspace/libparam_client/src/pp/i2c/i2c.c
Normal file
@ -0,0 +1,129 @@
|
||||
/* Copyright (c) 2013-2017 GomSpace A/S. All rights reserved. */
|
||||
|
||||
#define GS_PARAM_INTERNAL_USE 1
|
||||
|
||||
#include <gs/param/internal/pp/i2c/i2c.h>
|
||||
#include <gs/util/drivers/i2c/master.h>
|
||||
#include <gs/util/string.h>
|
||||
#include <gs/util/check.h>
|
||||
#include <alloca.h>
|
||||
|
||||
static gs_error_t gs_pp_i2c_write(gs_param_i2c_command_t cmd, gs_pp_t * pp, uint8_t table_id, uint16_t addr, void * value, size_t value_size, bool checksum)
|
||||
{
|
||||
GS_CHECK_RANGE(table_id <= 7);
|
||||
GS_CHECK_RANGE(addr <= 255);
|
||||
GS_CHECK_RANGE((value_size > 0) && (value_size <= 31));
|
||||
|
||||
gs_param_i2c_set_request_t * request;
|
||||
const size_t size = (sizeof(*request) + value_size + (checksum ? 1 : 0));
|
||||
request = alloca(size);
|
||||
|
||||
request->header.domain_command = GS_I2C_SLAVE_DISPATCH_HEADER(GS_I2C_SLAVE_DISPATCH_DOMAIN_PARAM, cmd);
|
||||
request->length_table = GS_PARAM_I2C_LENGTH_TABLE(value_size, table_id);
|
||||
request->addr = addr;
|
||||
memcpy(request->data, value, value_size);
|
||||
|
||||
if (checksum) {
|
||||
request->data[value_size] = gs_pp_checksum8(request, size - 1);
|
||||
}
|
||||
return gs_i2c_master_transaction(pp->pp.i2c.bus, pp->pp.i2c.addr, request, size, NULL, 0, 1000);
|
||||
|
||||
}
|
||||
|
||||
static gs_error_t gs_pp_i2c_read(gs_param_i2c_command_t cmd, gs_pp_t * pp, uint8_t table_id, uint16_t addr, void * value, size_t value_size, bool checksum)
|
||||
{
|
||||
GS_CHECK_RANGE(table_id <= 7);
|
||||
GS_CHECK_RANGE(addr <= 255);
|
||||
GS_CHECK_RANGE((value_size > 0) && (value_size <= 31));
|
||||
|
||||
gs_param_i2c_get_request_t request;
|
||||
memset(&request, 0, sizeof(request));
|
||||
request.length_table = GS_PARAM_I2C_LENGTH_TABLE(value_size, table_id);
|
||||
request.addr = addr;
|
||||
size_t request_size;
|
||||
|
||||
uint8_t reply[value_size + sizeof(request.checksum)]; // + for checksum
|
||||
memset(reply, 0, sizeof(reply));
|
||||
size_t reply_size;
|
||||
|
||||
request.header.domain_command = GS_I2C_SLAVE_DISPATCH_HEADER(GS_I2C_SLAVE_DISPATCH_DOMAIN_PARAM, cmd);
|
||||
|
||||
if (checksum) {
|
||||
request.checksum = gs_pp_checksum8(&request, (sizeof(request) - sizeof(request.checksum)));
|
||||
request_size = sizeof(request);
|
||||
reply_size = sizeof(reply);
|
||||
} else {
|
||||
request_size = sizeof(request) - sizeof(request.checksum);
|
||||
reply_size = sizeof(reply) - sizeof(request.checksum);
|
||||
}
|
||||
|
||||
gs_error_t error = gs_i2c_master_transaction(pp->pp.i2c.bus, pp->pp.i2c.addr, &request, request_size, reply, reply_size, 1000);
|
||||
if (error == GS_OK) {
|
||||
if (checksum) {
|
||||
if (gs_pp_checksum8(reply, value_size) != reply[value_size]) {
|
||||
return GS_ERROR_DATA;
|
||||
}
|
||||
}
|
||||
memcpy(value, reply, value_size);
|
||||
}
|
||||
return error;
|
||||
|
||||
}
|
||||
|
||||
static gs_error_t gs_pp_i2c_get(gs_pp_t * pp, uint8_t table_id, uint16_t addr, void * value, size_t value_size, uint32_t flags)
|
||||
{
|
||||
gs_param_i2c_command_t cmd;
|
||||
bool checksum = false;
|
||||
if (flags & GS_PP_FLAG_CHECKSUM) {
|
||||
checksum = true;
|
||||
cmd = GS_PARAM_I2C_COMMAND_GET_WITH_CHECKSUM;
|
||||
} else {
|
||||
cmd = GS_PARAM_I2C_COMMAND_GET;
|
||||
}
|
||||
return gs_pp_i2c_read(cmd, pp, table_id, addr, value, value_size, checksum);
|
||||
}
|
||||
|
||||
static gs_error_t gs_pp_i2c_set(gs_pp_t * pp, uint8_t table_id, uint16_t addr, const void * value, size_t value_size, uint32_t flags)
|
||||
{
|
||||
gs_param_i2c_command_t cmd;
|
||||
bool checksum = false;
|
||||
if (flags & GS_PP_FLAG_CHECKSUM) {
|
||||
checksum = true;
|
||||
cmd = GS_PARAM_I2C_COMMAND_SET_WITH_CHECKSUM;
|
||||
} else {
|
||||
cmd = GS_PARAM_I2C_COMMAND_SET;
|
||||
}
|
||||
return gs_pp_i2c_write(cmd, pp, table_id, addr, (void *)value, value_size, checksum);
|
||||
}
|
||||
|
||||
static gs_error_t gs_pp_i2c_set_table_lock(gs_pp_t * pp, uint8_t table_id, const bool * value, uint32_t flags)
|
||||
{
|
||||
gs_param_i2c_command_t cmd = GS_PARAM_I2C_COMMAND_SET_LOCK_WITH_CHECKSUM;
|
||||
bool checksum = true;
|
||||
return gs_pp_i2c_write(cmd, pp, table_id, 0, (void *)value, 1, checksum);
|
||||
}
|
||||
|
||||
static gs_error_t gs_pp_i2c_get_table_lock(gs_pp_t * pp, uint8_t table_id, bool * value, uint32_t flags)
|
||||
{
|
||||
gs_param_i2c_command_t cmd = GS_PARAM_I2C_COMMAND_GET_LOCK_WITH_CHECKSUM;
|
||||
bool checksum = true;
|
||||
return gs_pp_i2c_read(cmd, pp, table_id, 0, value, 1, checksum);
|
||||
}
|
||||
|
||||
gs_error_t gs_pp_i2c_init(gs_pp_t * pp, uint8_t bus, uint8_t addr, bool big_endian)
|
||||
{
|
||||
GS_CHECK_HANDLE(pp != NULL);
|
||||
|
||||
memset(pp, 0, sizeof(*pp));
|
||||
|
||||
pp->get = gs_pp_i2c_get;
|
||||
pp->set = gs_pp_i2c_set;
|
||||
pp->set_table_lock = gs_pp_i2c_set_table_lock;
|
||||
pp->get_table_lock = gs_pp_i2c_get_table_lock;
|
||||
pp->big_endian = big_endian;
|
||||
|
||||
pp->pp.i2c.bus = bus;
|
||||
pp->pp.i2c.addr = addr;
|
||||
|
||||
return GS_OK;
|
||||
}
|
189
gomspace/libparam_client/src/pp/pp.c
Normal file
189
gomspace/libparam_client/src/pp/pp.c
Normal file
@ -0,0 +1,189 @@
|
||||
/* Copyright (c) 2013-2017 GomSpace A/S. All rights reserved. */
|
||||
|
||||
#include <gs/param/pp/pp.h>
|
||||
#include <gs/util/string.h>
|
||||
#include <gs/util/check.h>
|
||||
#include <gs/util/byteorder.h>
|
||||
#include <gs/util/endian.h>
|
||||
|
||||
static inline bool gs_pp_endian_convert(gs_pp_t * pp)
|
||||
{
|
||||
return (pp && (pp->big_endian != gs_endian_big()));
|
||||
}
|
||||
|
||||
static gs_error_t gs_pp_get(gs_pp_t * pp, uint8_t table_id, uint16_t addr, void * value, size_t value_size, uint32_t flags)
|
||||
{
|
||||
if (pp == NULL) {
|
||||
return GS_ERROR_HANDLE;
|
||||
}
|
||||
if (pp->get == NULL) {
|
||||
return GS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
return pp->get(pp, table_id, addr, value, value_size, flags);
|
||||
}
|
||||
|
||||
static gs_error_t gs_pp_set(gs_pp_t * pp, uint8_t table_id, uint16_t addr, const void * value, size_t value_size, uint32_t flags)
|
||||
{
|
||||
if (pp == NULL) {
|
||||
return GS_ERROR_HANDLE;
|
||||
}
|
||||
if (pp->set == NULL) {
|
||||
return GS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
return pp->set(pp, table_id, addr, value, value_size, flags);
|
||||
}
|
||||
|
||||
uint8_t gs_pp_checksum8(const void * data_in, size_t length)
|
||||
{
|
||||
const uint8_t * data = data_in;
|
||||
unsigned int checksum = 0;
|
||||
for (unsigned int i = 0; i < length; ++i) {
|
||||
checksum += *data++;
|
||||
}
|
||||
checksum &= 0xff;
|
||||
return checksum ? checksum : 1;
|
||||
}
|
||||
|
||||
gs_error_t gs_pp_get_table_lock(gs_pp_t * pp, uint8_t table_id, bool * value, uint32_t flags)
|
||||
{
|
||||
GS_CHECK_ARG(value != NULL);
|
||||
GS_CHECK_HANDLE(pp != NULL);
|
||||
if (pp->get_table_lock == NULL) {
|
||||
return GS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
return pp->get_table_lock(pp, table_id, value, flags);
|
||||
}
|
||||
|
||||
gs_error_t gs_pp_set_table_lock(gs_pp_t * pp, uint8_t table_id, const bool * value, uint32_t flags)
|
||||
{
|
||||
GS_CHECK_ARG(value != NULL);
|
||||
GS_CHECK_HANDLE(pp != NULL);
|
||||
if (pp->set_table_lock == NULL) {
|
||||
return GS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
return pp->set_table_lock(pp, table_id, value, flags);
|
||||
}
|
||||
|
||||
// int8_t
|
||||
gs_error_t gs_pp_get_int8(gs_pp_t * pp, uint8_t table_id, uint8_t addr, int8_t * value, size_t count, uint32_t flags)
|
||||
{
|
||||
return gs_pp_get_uint8(pp, table_id, addr, (uint8_t *) value, count, flags);
|
||||
}
|
||||
|
||||
gs_error_t gs_pp_set_int8(gs_pp_t * pp, uint8_t table_id, uint8_t addr, const int8_t * value, size_t count, uint32_t flags)
|
||||
{
|
||||
return gs_pp_set_uint8(pp, table_id, addr, (const uint8_t *) value, count, flags);
|
||||
}
|
||||
|
||||
// uint8_t
|
||||
|
||||
gs_error_t gs_pp_get_uint8(gs_pp_t * pp, uint8_t table_id, uint8_t addr, uint8_t * value, size_t count, uint32_t flags)
|
||||
{
|
||||
GS_CHECK_ARG(value != NULL);
|
||||
GS_CHECK_ARG(count > 0);
|
||||
return gs_pp_get(pp, table_id, addr, value, (sizeof(*value) * count), flags);
|
||||
}
|
||||
|
||||
gs_error_t gs_pp_set_uint8(gs_pp_t * pp, uint8_t table_id, uint8_t addr, const uint8_t * value, size_t count, uint32_t flags)
|
||||
{
|
||||
GS_CHECK_ARG(value != NULL);
|
||||
GS_CHECK_ARG(count > 0);
|
||||
return gs_pp_set(pp, table_id, addr, value, (sizeof(*value) * count), flags);
|
||||
}
|
||||
|
||||
// int16_t
|
||||
|
||||
gs_error_t gs_pp_get_int16(gs_pp_t * pp, uint8_t table_id, uint8_t addr, int16_t * value, size_t count, uint32_t flags)
|
||||
{
|
||||
return gs_pp_get_uint16(pp, table_id, addr, (uint16_t *) value, count, flags);
|
||||
}
|
||||
|
||||
gs_error_t gs_pp_set_int16(gs_pp_t * pp, uint8_t table_id, uint8_t addr, const int16_t * value, size_t count, uint32_t flags)
|
||||
{
|
||||
return gs_pp_set_uint16(pp, table_id, addr, (const uint16_t *) value, count, flags);
|
||||
}
|
||||
|
||||
// uint16_t
|
||||
|
||||
gs_error_t gs_pp_get_uint16(gs_pp_t * pp, uint8_t table_id, uint8_t addr, uint16_t * value, size_t count, uint32_t flags)
|
||||
{
|
||||
GS_CHECK_ARG(value != NULL);
|
||||
GS_CHECK_ARG(count > 0);
|
||||
gs_error_t error = gs_pp_get(pp, table_id, addr, value, (sizeof(*value) * count), flags);
|
||||
if (gs_pp_endian_convert(pp)) {
|
||||
gs_bswap_16_array(value, value, count);
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
gs_error_t gs_pp_set_uint16(gs_pp_t * pp, uint8_t table_id, uint8_t addr, const uint16_t * value, size_t count, uint32_t flags)
|
||||
{
|
||||
GS_CHECK_ARG(value != NULL);
|
||||
GS_CHECK_ARG(count > 0);
|
||||
uint16_t _converted[count];
|
||||
if (gs_pp_endian_convert(pp)) {
|
||||
gs_bswap_16_array(value, _converted, count);
|
||||
value = _converted;
|
||||
}
|
||||
return gs_pp_set(pp, table_id, addr, value, (sizeof(*value) * count), flags);
|
||||
}
|
||||
|
||||
// int32_t
|
||||
|
||||
gs_error_t gs_pp_get_int32(gs_pp_t * pp, uint8_t table_id, uint8_t addr, int32_t * value, size_t count, uint32_t flags)
|
||||
{
|
||||
return gs_pp_get_uint32(pp, table_id, addr, (uint32_t *) value, count, flags);
|
||||
}
|
||||
|
||||
gs_error_t gs_pp_set_int32(gs_pp_t * pp, uint8_t table_id, uint8_t addr, const int32_t * value, size_t count, uint32_t flags)
|
||||
{
|
||||
return gs_pp_set_uint32(pp, table_id, addr, (const uint32_t *) value, count, flags);
|
||||
}
|
||||
|
||||
// uint32_t
|
||||
|
||||
gs_error_t gs_pp_get_uint32(gs_pp_t * pp, uint8_t table_id, uint8_t addr, uint32_t * value, size_t count, uint32_t flags)
|
||||
{
|
||||
GS_CHECK_ARG(value != NULL);
|
||||
GS_CHECK_ARG(count > 0);
|
||||
gs_error_t error = gs_pp_get(pp, table_id, addr, value, (sizeof(*value) * count), flags);
|
||||
if (gs_pp_endian_convert(pp)) {
|
||||
gs_bswap_32_array(value, value, count);
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
gs_error_t gs_pp_set_uint32(gs_pp_t * pp, uint8_t table_id, uint8_t addr, const uint32_t * value, size_t count, uint32_t flags)
|
||||
{
|
||||
GS_CHECK_ARG(value != NULL);
|
||||
GS_CHECK_ARG(count > 0);
|
||||
uint32_t _converted[count];
|
||||
if (gs_pp_endian_convert(pp)) {
|
||||
gs_bswap_32_array(value, _converted, count);
|
||||
value = _converted;
|
||||
}
|
||||
return gs_pp_set(pp, table_id, addr, value, (sizeof(*value) * count), flags);
|
||||
}
|
||||
|
||||
gs_error_t gs_pp_get_float(gs_pp_t * pp, uint8_t table_id, uint8_t addr, float * value, size_t count, uint32_t flags)
|
||||
{
|
||||
GS_CHECK_ARG(value != NULL);
|
||||
GS_CHECK_ARG(count > 0);
|
||||
gs_error_t error = gs_pp_get(pp, table_id, addr, value, (sizeof(*value) * count), flags);
|
||||
if (gs_pp_endian_convert(pp)) {
|
||||
gs_bswap_float_array(value, value, count);
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
gs_error_t gs_pp_set_float(gs_pp_t * pp, uint8_t table_id, uint8_t addr, const float * value, size_t count, uint32_t flags)
|
||||
{
|
||||
GS_CHECK_ARG(value != NULL);
|
||||
GS_CHECK_ARG(count > 0);
|
||||
float _converted[count];
|
||||
if (gs_pp_endian_convert(pp)) {
|
||||
gs_bswap_float_array(value, _converted, count);
|
||||
value = _converted;
|
||||
}
|
||||
return gs_pp_set(pp, table_id, addr, value, (sizeof(*value) * count), flags);
|
||||
}
|
91
gomspace/libparam_client/src/pp/spi/spi.c
Normal file
91
gomspace/libparam_client/src/pp/spi/spi.c
Normal file
@ -0,0 +1,91 @@
|
||||
/* Copyright (c) 2013-2017 GomSpace A/S. All rights reserved. */
|
||||
|
||||
#define GS_PARAM_INTERNAL_USE 1
|
||||
|
||||
#include <gs/param/internal/pp/spi/spi.h>
|
||||
#include <gs/util/drivers/spi/master.h>
|
||||
#include <gs/util/string.h>
|
||||
#include <gs/util/check.h>
|
||||
#include <alloca.h>
|
||||
|
||||
static gs_error_t gs_pp_spi_get(gs_pp_t * pp, uint8_t table_id, uint16_t addr, void * value, size_t value_size, uint32_t flags)
|
||||
{
|
||||
GS_CHECK_RANGE(table_id <= 7);
|
||||
GS_CHECK_RANGE(addr <= 255);
|
||||
|
||||
if (flags & GS_PP_FLAG_CHECKSUM) {
|
||||
gs_param_spi_get_with_checksum_t * request;
|
||||
const size_t size = (sizeof(*request) + value_size + 1); // +1 for CHECKSUM in returned data
|
||||
request = alloca(size);
|
||||
memset(request, 0, size);
|
||||
request->header.domain_command = GS_SPI_SLAVE_DISPATCH_HEADER(GS_SPI_SLAVE_DISPATCH_DOMAIN_PARAM, GS_PARAM_SPI_COMMAND_GET_WITH_CHECKSUM);
|
||||
request->length_table = GS_PARAM_SPI_LENGTH_TABLE(value_size, table_id);
|
||||
request->addr = addr;
|
||||
request->checksum = gs_pp_checksum8(request, (sizeof(*request) - sizeof(request->filler)));
|
||||
|
||||
gs_error_t error = gs_spi_master_transaction(pp->pp.spi.slave, request, request, size, 1000);
|
||||
if (error == GS_OK) {
|
||||
if (gs_pp_checksum8(request->data, value_size) != request->data[value_size]) {
|
||||
return GS_ERROR_DATA;
|
||||
}
|
||||
memcpy(value, request->data, value_size);
|
||||
}
|
||||
return error;
|
||||
|
||||
} else {
|
||||
gs_param_spi_get_t * request;
|
||||
const size_t size = (sizeof(*request) + value_size);
|
||||
request = alloca(size);
|
||||
memset(request, 0, size);
|
||||
request->header.domain_command = GS_SPI_SLAVE_DISPATCH_HEADER(GS_SPI_SLAVE_DISPATCH_DOMAIN_PARAM, GS_PARAM_SPI_COMMAND_GET);
|
||||
request->length_table = GS_PARAM_SPI_LENGTH_TABLE(value_size, table_id);
|
||||
request->addr = addr;
|
||||
|
||||
gs_error_t error = gs_spi_master_transaction(pp->pp.spi.slave, request, request, size, 1000);
|
||||
if (error == GS_OK) {
|
||||
memcpy(value, request->data, value_size);
|
||||
}
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
static gs_error_t gs_pp_spi_set(gs_pp_t * pp, uint8_t table_id, uint16_t addr, const void * value, size_t value_size, uint32_t flags)
|
||||
{
|
||||
GS_CHECK_RANGE(table_id <= 7);
|
||||
GS_CHECK_RANGE(addr <= 255);
|
||||
|
||||
gs_param_spi_set_t * request;
|
||||
const size_t size = (sizeof(*request) + value_size + ((flags & GS_PP_FLAG_CHECKSUM) ? 1 : 0));
|
||||
request = alloca(size);
|
||||
if (flags & GS_PP_FLAG_CHECKSUM) {
|
||||
request->header.domain_command = GS_SPI_SLAVE_DISPATCH_HEADER(GS_SPI_SLAVE_DISPATCH_DOMAIN_PARAM, GS_PARAM_SPI_COMMAND_SET_WITH_CHECKSUM);
|
||||
} else {
|
||||
request->header.domain_command = GS_SPI_SLAVE_DISPATCH_HEADER(GS_SPI_SLAVE_DISPATCH_DOMAIN_PARAM, GS_PARAM_SPI_COMMAND_SET);
|
||||
}
|
||||
request->length_table = GS_PARAM_SPI_LENGTH_TABLE(value_size, table_id);
|
||||
request->addr = addr;
|
||||
memcpy(request->data, value, value_size);
|
||||
|
||||
if (flags & GS_PP_FLAG_CHECKSUM) {
|
||||
request->data[value_size] = gs_pp_checksum8(request, size - 1);
|
||||
}
|
||||
|
||||
return gs_spi_master_transaction(pp->pp.spi.slave, request, NULL, size, 1000);
|
||||
}
|
||||
|
||||
gs_error_t gs_pp_spi_init(gs_pp_t * pp, uint8_t slave, bool big_endian)
|
||||
{
|
||||
GS_CHECK_HANDLE(pp != NULL);
|
||||
|
||||
memset(pp, 0, sizeof(*pp));
|
||||
|
||||
pp->get = gs_pp_spi_get;
|
||||
pp->set = gs_pp_spi_set;
|
||||
pp->set_table_lock = NULL; // Not implemented
|
||||
pp->get_table_lock = NULL; // Not implemented
|
||||
pp->big_endian = big_endian;
|
||||
|
||||
pp->pp.spi.slave = slave;
|
||||
|
||||
return GS_OK;
|
||||
}
|
Reference in New Issue
Block a user