basecmd: Generalize the "move queue" runtime storage

Detect the maximum size of each "move queue" item during the
configuration phase instead of using the stepper move struct.  This
allows the stepper code to be contained entirely in stepper.c and it
allows for future run time allocations from other types of objects.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
This commit is contained in:
Kevin O'Connor 2017-03-08 11:29:27 -05:00
parent affdbbf9ca
commit 37bac916e7
3 changed files with 86 additions and 42 deletions

View File

@ -17,26 +17,53 @@
* Move queue * Move queue
****************************************************************/ ****************************************************************/
static struct move *move_list, *move_free_list; struct move_freed {
static uint16_t move_count; struct move_freed *next;
};
void static struct move_freed *move_free_list;
move_free(struct move *m) static void *move_list;
static uint16_t move_count;
static uint8_t move_item_size;
// Is the config and move queue finalized?
static int
is_finalized(void)
{ {
m->next = move_free_list; return !!move_count;
move_free_list = m;
} }
struct move * // Free previously allocated storage from move_alloc(). Caller must
// disable irqs.
void
move_free(void *m)
{
struct move_freed *mf = m;
mf->next = move_free_list;
move_free_list = mf;
}
// Allocate runtime storage
void *
move_alloc(void) move_alloc(void)
{ {
irqstatus_t flag = irq_save(); irqstatus_t flag = irq_save();
struct move *m = move_free_list; struct move_freed *mf = move_free_list;
if (!m) if (!mf)
shutdown("Move queue empty"); shutdown("Move queue empty");
move_free_list = m->next; move_free_list = mf->next;
irq_restore(flag); irq_restore(flag);
return m; return mf;
}
// Request minimum size of runtime allocations returned by move_alloc()
void
move_request_size(int size)
{
if (size > UINT8_MAX || is_finalized())
shutdown("Invalid move request size");
if (size > move_item_size)
move_item_size = size;
} }
static void static void
@ -46,13 +73,28 @@ move_reset(void)
return; return;
// Add everything in move_list to the free list. // Add everything in move_list to the free list.
uint32_t i; uint32_t i;
for (i=0; i<move_count-1; i++) for (i=0; i<move_count-1; i++) {
move_list[i].next = &move_list[i+1]; struct move_freed *mf = move_list + i*move_item_size;
move_list[move_count-1].next = NULL; mf->next = move_list + (i + 1)*move_item_size;
move_free_list = &move_list[0]; }
struct move_freed *mf = move_list + (move_count - 1)*move_item_size;
mf->next = NULL;
move_free_list = move_list;
} }
DECL_SHUTDOWN(move_reset); DECL_SHUTDOWN(move_reset);
static void
move_finalize(void)
{
move_request_size(sizeof(*move_free_list));
uint16_t count = alloc_maxsize(move_item_size*1024) / move_item_size;
move_list = malloc(count * move_item_size);
if (!count || !move_list)
shutdown("move queue malloc failed");
move_count = count;
move_reset();
}
/**************************************************************** /****************************************************************
* Generic object ids (oid) * Generic object ids (oid)
@ -64,8 +106,6 @@ struct oid_s {
static struct oid_s *oids; static struct oid_s *oids;
static uint8_t num_oid; static uint8_t num_oid;
static uint32_t config_crc;
static uint8_t config_finalized;
void * void *
lookup_oid(uint8_t oid, void *type) lookup_oid(uint8_t oid, void *type)
@ -78,7 +118,7 @@ lookup_oid(uint8_t oid, void *type)
static void static void
assign_oid(uint8_t oid, void *type, void *data) assign_oid(uint8_t oid, void *type, void *data)
{ {
if (oid >= num_oid || oids[oid].type || config_finalized) if (oid >= num_oid || oids[oid].type || is_finalized())
shutdown("Can't assign oid"); shutdown("Can't assign oid");
oids[oid].type = type; oids[oid].type = type;
oids[oid].data = data; oids[oid].data = data;
@ -124,27 +164,28 @@ command_allocate_oids(uint32_t *args)
} }
DECL_COMMAND(command_allocate_oids, "allocate_oids count=%c"); DECL_COMMAND(command_allocate_oids, "allocate_oids count=%c");
/****************************************************************
* Config CRC
****************************************************************/
static uint32_t config_crc;
void void
command_get_config(uint32_t *args) command_get_config(uint32_t *args)
{ {
sendf("config is_config=%c crc=%u move_count=%hu" sendf("config is_config=%c crc=%u move_count=%hu"
, config_finalized, config_crc, move_count); , is_finalized(), config_crc, move_count);
} }
DECL_COMMAND_FLAGS(command_get_config, HF_IN_SHUTDOWN, "get_config"); DECL_COMMAND_FLAGS(command_get_config, HF_IN_SHUTDOWN, "get_config");
void void
command_finalize_config(uint32_t *args) command_finalize_config(uint32_t *args)
{ {
if (!oids || config_finalized) if (!oids || is_finalized())
shutdown("Can't finalize"); shutdown("Can't finalize");
uint16_t count = alloc_maxsize(sizeof(*move_list)*1024) / sizeof(*move_list); move_finalize();
move_list = malloc(count * sizeof(*move_list));
if (!count || !move_list)
shutdown("malloc failed");
move_count = count;
move_reset();
config_crc = args[0]; config_crc = args[0];
config_finalized = 1;
command_get_config(NULL); command_get_config(NULL);
} }
DECL_COMMAND(command_finalize_config, "finalize_config crc=%u"); DECL_COMMAND(command_finalize_config, "finalize_config crc=%u");

View File

@ -3,16 +3,9 @@
#include <stdint.h> // uint8_t #include <stdint.h> // uint8_t
struct move { void move_free(void *m);
uint32_t interval; void *move_alloc(void);
int16_t add; void move_request_size(int size);
uint16_t count;
struct move *next;
uint8_t flags;
};
void move_free(struct move *m);
struct move *move_alloc(void);
void *lookup_oid(uint8_t oid, void *type); void *lookup_oid(uint8_t oid, void *type);
void *alloc_oid(uint8_t oid, void *type, uint16_t size); void *alloc_oid(uint8_t oid, void *type, uint16_t size);
void *next_oid(uint8_t *i, void *type); void *next_oid(uint8_t *i, void *type);

View File

@ -17,6 +17,16 @@
* Steppers * Steppers
****************************************************************/ ****************************************************************/
struct stepper_move {
uint32_t interval;
int16_t add;
uint16_t count;
struct stepper_move *next;
uint8_t flags;
};
enum { MF_DIR=1<<0 };
struct stepper { struct stepper {
struct timer time; struct timer time;
uint32_t interval; uint32_t interval;
@ -30,13 +40,12 @@ struct stepper {
#endif #endif
struct gpio_out step_pin, dir_pin; struct gpio_out step_pin, dir_pin;
uint32_t position; uint32_t position;
struct move *first, **plast; struct stepper_move *first, **plast;
uint32_t min_stop_interval; uint32_t min_stop_interval;
// gcc (pre v6) does better optimization when uint8_t are bitfields // gcc (pre v6) does better optimization when uint8_t are bitfields
uint8_t flags : 8; uint8_t flags : 8;
}; };
enum { MF_DIR=1<<0 };
enum { SF_LAST_DIR=1<<0, SF_NEXT_DIR=1<<1, SF_INVERT_STEP=1<<2, SF_HAVE_ADD=1<<3, enum { SF_LAST_DIR=1<<0, SF_NEXT_DIR=1<<1, SF_INVERT_STEP=1<<2, SF_HAVE_ADD=1<<3,
SF_LAST_RESET=1<<4, SF_NO_NEXT_CHECK=1<<5 }; SF_LAST_RESET=1<<4, SF_NO_NEXT_CHECK=1<<5 };
@ -44,7 +53,7 @@ enum { SF_LAST_DIR=1<<0, SF_NEXT_DIR=1<<1, SF_INVERT_STEP=1<<2, SF_HAVE_ADD=1<<3
static uint_fast8_t static uint_fast8_t
stepper_load_next(struct stepper *s, uint32_t min_next_time) stepper_load_next(struct stepper *s, uint32_t min_next_time)
{ {
struct move *m = s->first; struct stepper_move *m = s->first;
if (!m) { if (!m) {
if (s->interval - s->add < s->min_stop_interval if (s->interval - s->add < s->min_stop_interval
&& !(s->flags & SF_NO_NEXT_CHECK)) && !(s->flags & SF_NO_NEXT_CHECK))
@ -144,6 +153,7 @@ command_config_stepper(uint32_t *args)
s->dir_pin = gpio_out_setup(args[2], 0); s->dir_pin = gpio_out_setup(args[2], 0);
s->min_stop_interval = args[3]; s->min_stop_interval = args[3];
s->position = -STEPPER_POSITION_BIAS; s->position = -STEPPER_POSITION_BIAS;
move_request_size(sizeof(struct stepper_move));
} }
DECL_COMMAND(command_config_stepper, DECL_COMMAND(command_config_stepper,
"config_stepper oid=%c step_pin=%c dir_pin=%c" "config_stepper oid=%c step_pin=%c dir_pin=%c"
@ -154,7 +164,7 @@ void
command_queue_step(uint32_t *args) command_queue_step(uint32_t *args)
{ {
struct stepper *s = lookup_oid(args[0], command_config_stepper); struct stepper *s = lookup_oid(args[0], command_config_stepper);
struct move *m = move_alloc(); struct stepper_move *m = move_alloc();
m->interval = args[1]; m->interval = args[1];
m->count = args[2]; m->count = args[2];
if (!m->count) if (!m->count)
@ -244,7 +254,7 @@ stepper_stop(struct stepper *s)
gpio_out_write(s->dir_pin, 0); gpio_out_write(s->dir_pin, 0);
gpio_out_write(s->step_pin, s->flags & SF_INVERT_STEP ? 1 : 0); gpio_out_write(s->step_pin, s->flags & SF_INVERT_STEP ? 1 : 0);
while (s->first) { while (s->first) {
struct move *next = s->first->next; struct stepper_move *next = s->first->next;
move_free(s->first); move_free(s->first);
s->first = next; s->first = next;
} }