diff --git a/src/basecmd.c b/src/basecmd.c index 4b4eca45..639add97 100644 --- a/src/basecmd.c +++ b/src/basecmd.c @@ -17,26 +17,53 @@ * Move queue ****************************************************************/ -static struct move *move_list, *move_free_list; -static uint16_t move_count; +struct move_freed { + struct move_freed *next; +}; -void -move_free(struct move *m) +static struct move_freed *move_free_list; +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; - move_free_list = m; + return !!move_count; } -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) { irqstatus_t flag = irq_save(); - struct move *m = move_free_list; - if (!m) + struct move_freed *mf = move_free_list; + if (!mf) shutdown("Move queue empty"); - move_free_list = m->next; + move_free_list = mf->next; 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 @@ -46,13 +73,28 @@ move_reset(void) return; // Add everything in move_list to the free list. uint32_t i; - for (i=0; inext = move_list + (i + 1)*move_item_size; + } + struct move_freed *mf = move_list + (move_count - 1)*move_item_size; + mf->next = NULL; + move_free_list = move_list; } 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) @@ -64,8 +106,6 @@ struct oid_s { static struct oid_s *oids; static uint8_t num_oid; -static uint32_t config_crc; -static uint8_t config_finalized; void * lookup_oid(uint8_t oid, void *type) @@ -78,7 +118,7 @@ lookup_oid(uint8_t oid, void *type) static void 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"); oids[oid].type = type; oids[oid].data = data; @@ -124,27 +164,28 @@ command_allocate_oids(uint32_t *args) } DECL_COMMAND(command_allocate_oids, "allocate_oids count=%c"); + +/**************************************************************** + * Config CRC + ****************************************************************/ + +static uint32_t config_crc; + void command_get_config(uint32_t *args) { 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"); void command_finalize_config(uint32_t *args) { - if (!oids || config_finalized) + if (!oids || is_finalized()) shutdown("Can't finalize"); - uint16_t count = alloc_maxsize(sizeof(*move_list)*1024) / sizeof(*move_list); - move_list = malloc(count * sizeof(*move_list)); - if (!count || !move_list) - shutdown("malloc failed"); - move_count = count; - move_reset(); + move_finalize(); config_crc = args[0]; - config_finalized = 1; command_get_config(NULL); } DECL_COMMAND(command_finalize_config, "finalize_config crc=%u"); diff --git a/src/basecmd.h b/src/basecmd.h index e5719c6f..b795e4db 100644 --- a/src/basecmd.h +++ b/src/basecmd.h @@ -3,16 +3,9 @@ #include // uint8_t -struct move { - uint32_t interval; - int16_t add; - uint16_t count; - struct move *next; - uint8_t flags; -}; - -void move_free(struct move *m); -struct move *move_alloc(void); +void move_free(void *m); +void *move_alloc(void); +void move_request_size(int size); void *lookup_oid(uint8_t oid, void *type); void *alloc_oid(uint8_t oid, void *type, uint16_t size); void *next_oid(uint8_t *i, void *type); diff --git a/src/stepper.c b/src/stepper.c index 23a073b1..b97a7a69 100644 --- a/src/stepper.c +++ b/src/stepper.c @@ -17,6 +17,16 @@ * 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 timer time; uint32_t interval; @@ -30,13 +40,12 @@ struct stepper { #endif struct gpio_out step_pin, dir_pin; uint32_t position; - struct move *first, **plast; + struct stepper_move *first, **plast; uint32_t min_stop_interval; // gcc (pre v6) does better optimization when uint8_t are bitfields 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, 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 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 (s->interval - s->add < s->min_stop_interval && !(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->min_stop_interval = args[3]; s->position = -STEPPER_POSITION_BIAS; + move_request_size(sizeof(struct stepper_move)); } DECL_COMMAND(command_config_stepper, "config_stepper oid=%c step_pin=%c dir_pin=%c" @@ -154,7 +164,7 @@ void command_queue_step(uint32_t *args) { 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->count = args[2]; if (!m->count) @@ -244,7 +254,7 @@ stepper_stop(struct stepper *s) gpio_out_write(s->dir_pin, 0); gpio_out_write(s->step_pin, s->flags & SF_INVERT_STEP ? 1 : 0); while (s->first) { - struct move *next = s->first->next; + struct stepper_move *next = s->first->next; move_free(s->first); s->first = next; }