From bf394f25dacac8e3e3add80ea326312cdd97ed00 Mon Sep 17 00:00:00 2001 From: Paul Selkirk Date: Thu, 27 Apr 2017 16:53:56 -0400 Subject: Replace the RTOS with a simple cooperative tasker. There are no priorities and no preemption, so tasks run in a round-robin fashion, and explicitly yield control. --- projects/hsm/Makefile | 9 +- projects/hsm/hsm.c | 377 +++++++++++++++++++++++++++++---------------- projects/hsm/mgmt-cli.c | 22 ++- projects/hsm/mgmt-task.c | 78 ++++++++++ projects/hsm/mgmt-task.h | 42 +++++ projects/hsm/mgmt-thread.c | 100 ------------ projects/hsm/mgmt-thread.h | 42 ----- 7 files changed, 378 insertions(+), 292 deletions(-) create mode 100644 projects/hsm/mgmt-task.c create mode 100644 projects/hsm/mgmt-task.h delete mode 100644 projects/hsm/mgmt-thread.c delete mode 100644 projects/hsm/mgmt-thread.h (limited to 'projects') diff --git a/projects/hsm/Makefile b/projects/hsm/Makefile index 6f941cf..d08fa52 100644 --- a/projects/hsm/Makefile +++ b/projects/hsm/Makefile @@ -8,7 +8,7 @@ OBJS = mgmt-cli.o \ mgmt-keystore.c \ mgmt-masterkey.c \ mgmt-misc.c \ - mgmt-thread.c \ + mgmt-task.c \ log.o BOARD_OBJS = \ @@ -22,20 +22,19 @@ BOARD_OBJS = \ $(TOPLEVEL)/stm-keystore.o \ $(TOPLEVEL)/stm-sdram.o \ $(TOPLEVEL)/stm-flash.o \ - $(BOARD_DIR)/TOOLCHAIN_GCC_ARM/startup_stm32f429xx_rtos.o \ + $(BOARD_DIR)/TOOLCHAIN_GCC_ARM/startup_stm32f429xx.o \ $(BOARD_DIR)/system_stm32f4xx.o \ $(BOARD_DIR)/stm32f4xx_hal_msp.o \ - $(BOARD_DIR)/stm32f4xx_it_rtos.o + $(BOARD_DIR)/stm32f4xx_it.o \ + $(TOPLEVEL)/task.o CFLAGS += -DNUM_RPC_TASK=4 CFLAGS += -I$(LIBHAL_SRC) CFLAGS += -I$(LIBCLI_SRC) -CFLAGS += -I$(RTOS_DIR)/rtos -I$(RTOS_DIR)/rtx/TARGET_CORTEX_M LIBS += $(LIBHAL_BLD)/libhal.a $(LIBTFM_BLD)/libtfm.a LIBS += $(LIBCLI_BLD)/libcli.a -LIBS += $(RTOS_DIR)/librtos.a all: $(PROJ:=.elf) diff --git a/projects/hsm/hsm.c b/projects/hsm/hsm.c index f71e2c2..a683b7f 100644 --- a/projects/hsm/hsm.c +++ b/projects/hsm/hsm.c @@ -44,13 +44,12 @@ /* Rename both CMSIS HAL_OK and libhal HAL_OK to disambiguate */ #define HAL_OK CMSIS_HAL_OK -#include "cmsis_os.h" - #include "stm-init.h" #include "stm-led.h" #include "stm-fmc.h" #include "stm-uart.h" #include "stm-sdram.h" +#include "task.h" #include "mgmt-cli.h" @@ -63,10 +62,9 @@ #undef HAL_OK #ifndef NUM_RPC_TASK -/* Just one RPC task for now. More will require active resource management - * of at least the FPGA cores. - */ #define NUM_RPC_TASK 1 +#elif NUM_RPC_TASK < 1 || NUM_RPC_TASK > 10 +#error invalid NUM_RPC_TASK #endif #ifndef TASK_STACK_SIZE @@ -77,6 +75,21 @@ #define TASK_STACK_SIZE 200*1024 #endif +/* Stack for the busy task. This doesn't need to be very big. + */ +#ifndef BUSY_STACK_SIZE +#define BUSY_STACK_SIZE 1*1024 +#endif +static uint8_t busy_stack[BUSY_STACK_SIZE]; + +/* Stack for the CLI task. This needs to be big enough to accept a + * 4096-byte block of an FPGA or bootloader image upload. + */ +#ifndef CLI_STACK_SIZE +#define CLI_STACK_SIZE 8*1024 +#endif +static uint8_t cli_stack[CLI_STACK_SIZE]; + #ifndef MAX_PKT_SIZE /* An arbitrary number, more or less driven by the 4096-bit RSA * keygen test. @@ -84,146 +97,238 @@ #define MAX_PKT_SIZE 4096 #endif -/* RPC buffers. For each active RPC, there will be two - input and output. +/* RPC buffers. For each active request, there will be two - input and output. */ -typedef struct { +typedef struct rpc_buffer_s { size_t len; uint8_t buf[MAX_PKT_SIZE]; + struct rpc_buffer_s *next; /* for ibuf queue linking */ } rpc_buffer_t; -/* A mail queue (memory pool + message queue) for RPC request messages. - */ -osMailQId ibuf_queue; -osMailQDef(ibuf_queue, NUM_RPC_TASK + 2, rpc_buffer_t); +/* RPC input (requst) buffers */ +static rpc_buffer_t ibufs[NUM_RPC_TASK]; -#if NUM_RPC_TASK > 1 -/* A mutex to arbitrate concurrent UART transmits, from RPC responses. - */ -osMutexId uart_mutex; -osMutexDef(uart_mutex); -static inline void uart_lock(void) { osMutexWait(uart_mutex, osWaitForever); } -static inline void uart_unlock(void) { osMutexRelease(uart_mutex); } -#else -static inline void uart_lock(void) { } -static inline void uart_unlock(void) { } -#endif +/* ibuf queue structure */ +typedef struct { + rpc_buffer_t *head, *tail; + size_t len, max; /* for reporting */ +} ibufq_t; -#if NUM_RPC_TASK > 1 -/* A mutex to arbitrate concurrent access to the keystore. +/* ibuf queues. These correspond roughly to task states - 'waiting' is for + * unallocated ibufs, while 'ready' is for requests that are ready to be + * processed. */ -osMutexId ks_mutex; -osMutexDef(ks_mutex); -void hal_ks_lock(void) { osMutexWait(ks_mutex, osWaitForever); } -void hal_ks_unlock(void) { osMutexRelease(ks_mutex); } -#endif +static ibufq_t ibuf_waiting, ibuf_ready; -/* A ring buffer for the UART DMA receiver. In theory, it should get at most - * 92 characters per 1ms tick, but we're going to up-size it for safety. - */ -#ifndef RPC_UART_RECVBUF_SIZE -#define RPC_UART_RECVBUF_SIZE 256 /* must be a power of 2 */ -#endif -#define RPC_UART_RECVBUF_MASK (RPC_UART_RECVBUF_SIZE - 1) +/* Get an ibuf from a queue. */ +static rpc_buffer_t *ibuf_get(ibufq_t *q) +{ + hal_critical_section_start(); + rpc_buffer_t *ibuf = q->head; + if (ibuf) { + q->head = ibuf->next; + if (q->head == NULL) + q->tail = NULL; + ibuf->next = NULL; + --q->len; + } + hal_critical_section_end(); + return ibuf; +} -typedef struct { - uint32_t ridx; - uint8_t buf[RPC_UART_RECVBUF_SIZE]; -} uart_ringbuf_t; +/* Put an ibuf on a queue. */ +static void ibuf_put(ibufq_t *q, rpc_buffer_t *ibuf) +{ + hal_critical_section_start(); + if (q->tail) + q->tail->next = ibuf; + else + q->head = ibuf; + q->tail = ibuf; + ibuf->next = NULL; + if (++q->len > q->max) + q->max = q->len; + hal_critical_section_end(); +} -volatile uart_ringbuf_t uart_ringbuf = {0, {0}}; +/* Get the current length of the 'ready' queue, for reporting in the CLI. */ +size_t request_queue_len(void) +{ + size_t n; + + hal_critical_section_start(); + n = ibuf_ready.len; + hal_critical_section_end(); + + return n; +} + +/* Get the maximum length of the 'ready' queue, for reporting in the CLI. */ +size_t request_queue_max(void) +{ + size_t n; -#define RINGBUF_RIDX(rb) (rb.ridx & RPC_UART_RECVBUF_MASK) -#define RINGBUF_WIDX(rb) (sizeof(rb.buf) - __HAL_DMA_GET_COUNTER(huart_user.hdmarx)) -#define RINGBUF_COUNT(rb) ((unsigned)(RINGBUF_WIDX(rb) - RINGBUF_RIDX(rb))) -#define RINGBUF_READ(rb, dst) {dst = rb.buf[RINGBUF_RIDX(rb)]; rb.ridx++;} + hal_critical_section_start(); + n = ibuf_ready.max; + hal_critical_section_end(); -/* Thread entry point for the UART DMA monitor. + return n; +} + +static void dispatch_task(void); +static void busy_task(void); +static tcb_t *busy_tcb; + +/* Select an available dispatch task. For simplicity, this doesn't try to + * allocate tasks in a round-robin fashion, so the lowest-numbered task + * will see the most action. OTOH, this lets us gauge the level of system + * activity in the CLI's 'task show' command. */ -void uart_rx_thread(void const *args) +static tcb_t *task_next_waiting(void) { - /* current RPC input buffer */ - rpc_buffer_t *ibuf = NULL; + for (tcb_t *t = task_iterate(NULL); t; t = task_iterate(t)) { + if (task_get_func(t) == dispatch_task && + task_get_state(t) == TASK_WAITING) + return t; + } + return NULL; +} - /* I wanted to call osThreadYield(), but the documentation is misleading, - * and it only yields to the next ready thread of the same priority, so - * this high-priority thread wouldn't let anything else run. osDelay(1) - * reschedules this thread for the next tick, which is what we want. +static uint8_t *sdram_malloc(size_t size); + +/* Callback for HAL_UART_Receive_DMA(). + */ +static void RxCallback(uint8_t c) +{ + int complete; + static rpc_buffer_t *ibuf = NULL; + + /* If we couldn't previously get an ibuf, a task may have freed one up + * in the meantime. Otherwise, allocate one from SDRAM. In normal + * operation, the number of ibufs will expand to the number of remote + * clients (which we don't know and can't predict). It would take an + * active attempt to DOS the system to exhaust SDRAM, and there are + * easier ways to attack the device (don't release hash or pkey handles). */ - for ( ; ; osDelay(1)) { + if (ibuf == NULL) { + ibuf = ibuf_get(&ibuf_waiting); if (ibuf == NULL) { - if ((ibuf = (rpc_buffer_t *)osMailAlloc(ibuf_queue, 1)) == NULL) - /* This could happen if all dispatch threads are busy, and - * there are NUM_RPC_TASK requests already queued. We could - * send a "server busy" error, or we could just try again on - * the next tick. - */ + ibuf = (rpc_buffer_t *)sdram_malloc(sizeof(rpc_buffer_t)); + if (ibuf == NULL) Error_Handler(); - ibuf->len = 0; } + ibuf->len = 0; + } - while (RINGBUF_COUNT(uart_ringbuf)) { - uint8_t c; - int complete; - - RINGBUF_READ(uart_ringbuf, c); - if (hal_slip_process_char(c, ibuf->buf, &ibuf->len, sizeof(ibuf->buf), &complete) != LIBHAL_OK) - Error_Handler(); + /* Process this character into the ibuf. */ + if (hal_slip_process_char(c, ibuf->buf, &ibuf->len, sizeof(ibuf->buf), &complete) != LIBHAL_OK) + Error_Handler(); - if (complete) { - if (osMailPut(ibuf_queue, (void *)ibuf) != osOK) - Error_Handler(); - ibuf = NULL; - /* Yield, to allow one of the dispatch threads to pick up this - * new request. - */ - break; - } - } + if (complete) { + /* Add the ibuf to the request queue, and try to get another ibuf. + */ + ibuf_put(&ibuf_ready, ibuf); + ibuf = ibuf_get(&ibuf_waiting); + if (ibuf != NULL) + ibuf->len = 0; + /* else all ibufs are busy, try again next time */ + + /* Wake a dispatch task to deal with this request, or wake the + * busy task to re-try scheduling a dispatch task. + */ + tcb_t *t = task_next_waiting(); + if (t) + task_wake(t); + else + task_wake(busy_tcb); } } -osThreadDef(uart_rx_thread, osPriorityHigh, DEFAULT_STACK_SIZE); +static uint8_t uart_rx[2]; /* current character received from UART */ +static uint32_t uart_rx_idx = 0; + +/* UART DMA half-complete and complete callbacks. With a 2-character DMA + * buffer, one or the other of these will fire on each incoming character. + * Under heavy load, these will sometimes fire in the wrong order, but the + * data are in the right order in the DMA buffer, so we have a flip-flop + * buffer index that doesn't depend on the order of the callbacks. + */ +void HAL_UART2_RxHalfCpltCallback(UART_HandleTypeDef *huart) +{ + RxCallback(uart_rx[uart_rx_idx]); + uart_rx_idx ^= 1; +} + +void HAL_UART2_RxCpltCallback(UART_HandleTypeDef *huart) +{ + RxCallback(uart_rx[uart_rx_idx]); + uart_rx_idx ^= 1; +} + +/* Send one character over the UART. This is called from + * hal_slip_send_char(). + */ hal_error_t hal_serial_send_char(uint8_t c) { return (uart_send_char2(STM_UART_USER, c) == 0) ? LIBHAL_OK : HAL_ERROR_RPC_TRANSPORT; } -/* Thread entry point for the RPC request handler. +/* Task entry point for the RPC request handler. */ -void dispatch_thread(void const *args) +static void dispatch_task(void) { - rpc_buffer_t obuf_s, *obuf = &obuf_s, *ibuf; + rpc_buffer_t obuf_s, *obuf = &obuf_s; while (1) { - memset(obuf, 0, sizeof(*obuf)); - obuf->len = sizeof(obuf->buf); - /* Wait for a complete RPC request */ - osEvent evt = osMailGet(ibuf_queue, osWaitForever); - if (evt.status != osEventMail) + task_sleep(); + + rpc_buffer_t *ibuf = ibuf_get(&ibuf_ready); + if (ibuf == NULL) + /* probably an error, but go back to sleep */ continue; - ibuf = (rpc_buffer_t *)evt.value.p; + + memset(obuf, 0, sizeof(*obuf)); + obuf->len = sizeof(obuf->buf); /* Process the request */ - hal_error_t ret = hal_rpc_server_dispatch(ibuf->buf, ibuf->len, obuf->buf, &obuf->len); - osMailFree(ibuf_queue, (void *)ibuf); - if (ret != LIBHAL_OK) { - /* If hal_rpc_server_dispatch failed with an XDR error, it - * probably means the request packet was garbage. In any case, we - * have nothing to transmit. - */ - continue; - } + hal_error_t ret = hal_rpc_server_dispatch(ibuf->buf, ibuf->len, obuf->buf, &obuf->len); + ibuf_put(&ibuf_waiting, ibuf); + if (ret == LIBHAL_OK) { + /* Send the response */ + if (hal_rpc_sendto(obuf->buf, obuf->len, NULL) != LIBHAL_OK) + Error_Handler(); + } + /* Else hal_rpc_server_dispatch failed with an XDR error, which + * probably means the request packet was garbage. In any case, we + * have nothing to transmit. + */ + } +} - /* Send the response */ - uart_lock(); - ret = hal_rpc_sendto(obuf->buf, obuf->len, NULL); - uart_unlock(); - if (ret != LIBHAL_OK) - Error_Handler(); +/* Task entry point for the task-rescheduling task. + */ +static void busy_task(void) +{ + while (1) { + /* Wake as many tasks as we have requests. + */ + size_t n; + for (n = request_queue_len(); n > 0; --n) { + tcb_t *t; + if ((t = task_next_waiting()) != NULL) + task_wake(t); + else + break; + } + if (n == 0) + /* flushed the queue, our work here is done */ + task_sleep(); + else + /* more work to do, try again after some tasks have run */ + task_yield(); } } -osThreadDef_t thread_def[NUM_RPC_TASK]; /* Allocate memory from SDRAM1. There is only malloc, no free, so we don't * worry about fragmentation. */ @@ -255,8 +360,7 @@ void *hal_allocate_static_memory(const size_t size) return sdram_malloc(size); } -#if NUM_RPC_TASK > 1 -/* Critical section start/end, currently used just for hal_core_alloc/_free. +/* Critical section start/end - temporarily disable interrupts. */ void hal_critical_section_start(void) { @@ -267,12 +371,19 @@ void hal_critical_section_end(void) { __enable_irq(); } -#endif -/* The main thread. This does all the setup, and the worker threads handle +/* A genericized public interface to task_yield(), for calling from + * libhal. + */ +void hal_task_yield(void) +{ + task_yield(); +} + +/* The main task. This does all the setup, and the worker tasks handle * the rest. */ -int main() +int main(void) { stm_init(); uart_set_default(STM_UART_MGMT); @@ -282,41 +393,43 @@ int main() fmc_init(); sdram_init(); - if ((ibuf_queue = osMailCreate(osMailQ(ibuf_queue), NULL)) == NULL) + if (hal_rpc_server_init() != LIBHAL_OK) Error_Handler(); -#if NUM_RPC_TASK > 1 - if ((uart_mutex = osMutexCreate(osMutex(uart_mutex))) == NULL) - Error_Handler(); - if ((ks_mutex = osMutexCreate(osMutex(ks_mutex))) == NULL) - Error_Handler(); -#endif - - if (hal_rpc_server_init() != LIBHAL_OK) - Error_Handler(); + /* Initialize the ibuf queues. */ + memset(&ibuf_waiting, 0, sizeof(ibuf_waiting)); + memset(&ibuf_ready, 0, sizeof(ibuf_ready)); + for (int i = 0; i < sizeof(ibufs)/sizeof(ibufs[0]); ++i) + ibuf_put(&ibuf_waiting, &ibufs[i]); - /* Create the rpc dispatch worker threads. */ + /* Create the rpc dispatch worker tasks. */ + static char label[NUM_RPC_TASK][sizeof("dispatch0")]; for (int i = 0; i < NUM_RPC_TASK; ++i) { - osThreadDef_t *ot = &thread_def[i]; - ot->pthread = dispatch_thread; - ot->tpriority = osPriorityNormal; - ot->stacksize = TASK_STACK_SIZE; - ot->stack_pointer = (uint32_t *)(sdram_malloc(TASK_STACK_SIZE)); - if (ot->stack_pointer == NULL) + sprintf(label[i], "dispatch%d", i); + void *stack = (void *)sdram_malloc(TASK_STACK_SIZE); + if (stack == NULL) Error_Handler(); - if (osThreadCreate(ot, (void *)i) == NULL) + if (task_add(label[i], dispatch_task, &ibufs[i], stack, TASK_STACK_SIZE) == NULL) Error_Handler(); } - /* Start the UART receiver. */ - if (HAL_UART_Receive_DMA(&huart_user, (uint8_t *) uart_ringbuf.buf, sizeof(uart_ringbuf.buf)) != CMSIS_HAL_OK) + /* Create the busy task. */ + busy_tcb = task_add("busy", busy_task, NULL, busy_stack, sizeof(busy_stack)); + if (busy_tcb == NULL) Error_Handler(); - if (osThreadCreate(osThread(uart_rx_thread), NULL) == NULL) + + /* Start the UART receiver. */ + if (HAL_UART_Receive_DMA(&huart_user, uart_rx, 2) != CMSIS_HAL_OK) Error_Handler(); - /* Launch other threads (csprng warm-up thread?) + /* Launch other tasks (csprng warm-up task?) * Wait for FPGA_DONE interrupt. */ - return cli_main(); + /* Create the CLI task. */ + if (task_add("cli", (funcp_t)cli_main, NULL, cli_stack, sizeof(cli_stack)) == NULL) + Error_Handler(); + + /* Start the tasker */ + task_yield(); } diff --git a/projects/hsm/mgmt-cli.c b/projects/hsm/mgmt-cli.c index 3c1a3bc..ec9bf8f 100644 --- a/projects/hsm/mgmt-cli.c +++ b/projects/hsm/mgmt-cli.c @@ -3,7 +3,7 @@ * --------- * Management CLI code. * - * Copyright (c) 2016, NORDUnet A/S All rights reserved. + * Copyright (c) 2016-2017, NORDUnet A/S All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -36,11 +36,10 @@ /* Rename both CMSIS HAL_OK and libhal HAL_OK to disambiguate */ #define HAL_OK CMSIS_HAL_OK -#include "cmsis_os.h" - #include "stm-init.h" #include "stm-uart.h" #include "stm-led.h" +#include "task.h" #include "mgmt-cli.h" #include "mgmt-firmware.h" @@ -49,7 +48,7 @@ #include "mgmt-misc.h" #include "mgmt-keystore.h" #include "mgmt-masterkey.h" -#include "mgmt-thread.h" +#include "mgmt-task.h" #undef HAL_OK #define HAL_OK LIBHAL_OK @@ -58,6 +57,8 @@ #include "hal_internal.h" #undef HAL_OK +static tcb_t *cli_task; + #ifndef CLI_UART_RECVBUF_SIZE #define CLI_UART_RECVBUF_SIZE 256 #endif @@ -98,17 +99,12 @@ static ringbuf_t uart_ringbuf; /* current character received from UART */ static uint8_t uart_rx; -/* Semaphore to inform uart_cli_read that there's a new character. - */ -osSemaphoreId uart_sem; -osSemaphoreDef(uart_sem); - /* Callback for HAL_UART_Receive_DMA(). */ void HAL_UART1_RxCpltCallback(UART_HandleTypeDef *huart) { ringbuf_write_char(&uart_ringbuf, uart_rx); - osSemaphoreRelease(uart_sem); + task_wake(cli_task); } static void uart_cli_print(struct cli_def *cli __attribute__ ((unused)), const char *buf) @@ -122,7 +118,7 @@ static ssize_t uart_cli_read(struct cli_def *cli __attribute__ ((unused)), void { for (int i = 0; i < count; ++i) { while (ringbuf_read_char(&uart_ringbuf, (uint8_t *)(buf + i)) == 0) - osSemaphoreWait(uart_sem, osWaitForever); + task_sleep(); } return (ssize_t)count; } @@ -175,7 +171,7 @@ static int check_auth(const char *username, const char *password) int cli_main(void) { - uart_sem = osSemaphoreCreate(osSemaphore(uart_sem), 0); + cli_task = task_get_tcb(); struct cli_def *cli; cli = cli_init(); @@ -198,7 +194,7 @@ int cli_main(void) configure_cli_firmware(cli); configure_cli_bootloader(cli); configure_cli_misc(cli); - configure_cli_thread(cli); + configure_cli_task(cli); while (1) { control_mgmt_uart_dma_rx(DMA_RX_START); diff --git a/projects/hsm/mgmt-task.c b/projects/hsm/mgmt-task.c new file mode 100644 index 0000000..a1ae7e6 --- /dev/null +++ b/projects/hsm/mgmt-task.c @@ -0,0 +1,78 @@ +/* + * mgmt-task.c + * ----------- + * CLI 'task' functions. + * + * Copyright (c) 2016-2017, NORDUnet A/S All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of the NORDUnet nor the names of its contributors may + * be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Show the active tasks. This is mostly for debugging, and looks deeply + * into OS-level structures, but sometimes you just need to know... + */ + +#include "mgmt-cli.h" +#include "mgmt-task.h" +#include "task.h" + +static char *task_state[] = { + "INIT", + "WAITING", + "READY" +}; + +extern size_t request_queue_len(void); +extern size_t request_queue_max(void); + +static int cmd_task_show(struct cli_def *cli, const char *command, char *argv[], int argc) +{ + cli_print(cli, "name state stack high water"); + cli_print(cli, "-------- -------- ----------------"); + + for (tcb_t *t = task_iterate(NULL); t != NULL; t = task_iterate(t)) { + cli_print(cli, "%-15s %-15s %d", + task_get_name(t), + task_state[task_get_state(t)], + task_get_stack_highwater(t)); + } + + cli_print(cli, " "); + cli_print(cli, "request queue current length: %d", request_queue_len()); + cli_print(cli, "request queue maximum length: %d", request_queue_max()); + + return CLI_OK; +} + +void configure_cli_task(struct cli_def *cli) +{ + struct cli_command *c = cli_register_command(cli, NULL, "task", NULL, 0, 0, NULL); + + /* task show */ + cli_register_command(cli, c, "show", cmd_task_show, 0, 0, "Show the active tasks"); +} diff --git a/projects/hsm/mgmt-task.h b/projects/hsm/mgmt-task.h new file mode 100644 index 0000000..f903962 --- /dev/null +++ b/projects/hsm/mgmt-task.h @@ -0,0 +1,42 @@ +/* + * mgmt-task.h + * ----------- + * Management CLI 'task' functions. + * + * Copyright (c) 2016-2017, NORDUnet A/S All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of the NORDUnet nor the names of its contributors may + * be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __STM32_CLI_MGMT_TASK_H +#define __STM32_CLI_MGMT_TASK_H + +#include + +extern void configure_cli_task(struct cli_def *cli); + +#endif /* __STM32_CLI_MGMT_TASK_H */ diff --git a/projects/hsm/mgmt-thread.c b/projects/hsm/mgmt-thread.c deleted file mode 100644 index 96776aa..0000000 --- a/projects/hsm/mgmt-thread.c +++ /dev/null @@ -1,100 +0,0 @@ -/* - * mgmt-thread.c - * ----------- - * CLI 'thread' functions. - * - * Copyright (c) 2016, NORDUnet A/S All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of the NORDUnet nor the names of its contributors may - * be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A - * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * Show the active threads. This is mostly for debugging, and looks deeply - * into OS-level structures, but sometimes you just need to know... - */ - -#include "mgmt-cli.h" -#include "mgmt-thread.h" - -/* rt_TypeDef.h redefines NULL (previously defined in stddef.h, via libcli.h) */ -#undef NULL - -#include "rt_TypeDef.h" -#include "RTX_Conf.h" - -static char *task_state[] = { - "INACTIVE", - "READY", - "RUNNING", - "WAIT_DLY", - "WAIT_ITV", - "WAIT_OR", - "WAIT_AND", - "WAIT_SEM", - "WAIT_MBX", - "WAIT_MUT", -}; - -static int cmd_thread_show(struct cli_def *cli, const char *command, char *argv[], int argc) -{ - OS_TID task_id; - P_TCB task; - char *name; - extern void main(void); - extern void dispatch_thread(void); - extern void osTimerThread(void); - extern void uart_rx_thread(void); - - for (task_id = 1; task_id <= os_maxtaskrun; ++ task_id) { - if ((task = os_active_TCB[task_id-1]) != NULL) { - if (task->ptask == main) - name = "main"; - else if (task->ptask == dispatch_thread) - name = "dispatch_thread"; - else if (task->ptask == osTimerThread) - name = "osTimerThread"; - else if (task->ptask == uart_rx_thread) - name = "uart_rx_thread"; - else - name = "unknown"; - - cli_print(cli, "%d:\tptask\t%p\t%s", task_id, task->ptask, name); - cli_print(cli, "\tstate\t%d\t\t%s", (int)task->state, task_state[task->state]); - cli_print(cli, "\tprio\t%d", (int)task->prio); - cli_print(cli, "\tstack\t%p", task->stack); - } - } - return CLI_OK; -} - -void configure_cli_thread(struct cli_def *cli) -{ - struct cli_command *c = cli_register_command(cli, NULL, "thread", NULL, 0, 0, NULL); - - /* thread show */ - cli_register_command(cli, c, "show", cmd_thread_show, 0, 0, "Show the active threads"); -} diff --git a/projects/hsm/mgmt-thread.h b/projects/hsm/mgmt-thread.h deleted file mode 100644 index f72695e..0000000 --- a/projects/hsm/mgmt-thread.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * mgmt-thread.h - * ----------- - * Management CLI 'thread' functions. - * - * Copyright (c) 2016, NORDUnet A/S All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of the NORDUnet nor the names of its contributors may - * be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A - * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __STM32_CLI_MGMT_THREAD_H -#define __STM32_CLI_MGMT_THREAD_H - -#include - -extern void configure_cli_thread(struct cli_def *cli); - -#endif /* __STM32_CLI_MGMT_THREAD_H */ -- cgit v1.2.3