save failed integration state

This commit is contained in:
2020-11-26 10:24:23 +01:00
parent 473aa805c0
commit 6bd55e7c22
194 changed files with 45450 additions and 2 deletions

View 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);
}

View 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;
}

View 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);
}

View 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;
}