From db6a9b4d96f7030f24541813f53d0e6826afee9c Mon Sep 17 00:00:00 2001 From: Kevin O'Connor Date: Tue, 10 May 2022 13:12:57 -0400 Subject: [PATCH] sched: Add sched.c and sched.h files to make importing Klipper code easier Add the sched.c code and associated DECL_INIT(), DECL_TASK() macros so that it is easier to import low-level Klipper code into the CanBoot repo. These additional code wrappers do not increase the overall binary size as gcc does a good job of inlining the wrappers and removing unused code during the compile process. Signed-off-by: Kevin O'Connor --- scripts/buildcommands.py | 38 ++++++++++++++++++++++++++++++++ src/Makefile | 2 +- src/canboot_main.c | 7 +++--- src/generic/armcm_irq.c | 2 ++ src/generic/canbus.c | 47 +++++++++++++++++++++------------------- src/generic/canbus.h | 3 --- src/led.c | 2 ++ src/led.h | 1 - src/sched.c | 41 +++++++++++++++++++++++++++++++++++ src/sched.h | 29 +++++++++++++++++++++++++ src/stm32/can.c | 3 ++- 11 files changed, 143 insertions(+), 32 deletions(-) create mode 100644 src/sched.c create mode 100644 src/sched.h diff --git a/scripts/buildcommands.py b/scripts/buildcommands.py index 757535c..2a44843 100644 --- a/scripts/buildcommands.py +++ b/scripts/buildcommands.py @@ -10,6 +10,7 @@ FILEHEADER = """ /* DO NOT EDIT! This is an autogenerated file. See scripts/buildcommands.py. */ #include +#include "board/irq.h" #include "compiler.h" """ @@ -19,6 +20,43 @@ def error(msg): Handlers = [] + +###################################################################### +# C call list generation +###################################################################### + +# Create dynamic C functions that call a list of other C functions +class HandleCallList: + def __init__(self): + self.call_lists = {'ctr_run_initfuncs': []} + self.ctr_dispatch = { '_DECL_CALLLIST': self.decl_calllist } + def decl_calllist(self, req): + funcname, callname = req.split()[1:] + self.call_lists.setdefault(funcname, []).append(callname) + def update_data_dictionary(self, data): + pass + def generate_code(self, options): + code = [] + for funcname, funcs in self.call_lists.items(): + func_code = [' extern void %s(void);\n %s();' % (f, f) + for f in funcs] + if funcname == 'ctr_run_taskfuncs': + add_poll = ' irq_poll();\n' + func_code = [add_poll + fc for fc in func_code] + func_code.append(add_poll) + fmt = """ +void +%s(void) +{ + %s +} +""" + code.append(fmt % (funcname, "\n".join(func_code).strip())) + return "".join(code) + +Handlers.append(HandleCallList()) + + ###################################################################### # Enumeration and static string generation ###################################################################### diff --git a/src/Makefile b/src/Makefile index 446861b..3e8973e 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,3 +1,3 @@ # Main code build rules -src-y += canboot_main.c led.c +src-y += canboot_main.c sched.c led.c diff --git a/src/canboot_main.c b/src/canboot_main.c index 386b7eb..2e970d7 100644 --- a/src/canboot_main.c +++ b/src/canboot_main.c @@ -14,6 +14,7 @@ #include "ctr.h" // DECL_CTR #include "led.h" // check_blink_time #include "byteorder.h" // cpu_to_le32 +#include "sched.h" // sched_run_init #define PROTO_VERSION 0x00010000 // Version 1.0.0 #define PROTO_SIZE 4 @@ -291,12 +292,10 @@ check_double_reset(void) static void enter_bootloader(void) { - can_init(); - led_init(); + sched_run_init(); for (;;) { - canbus_rx_task(); - canbus_tx_task(); + sched_run_tasks(); check_blink_time(blink_time); if (complete && canbus_tx_clear()) // wait until we are complete and the ack has returned diff --git a/src/generic/armcm_irq.c b/src/generic/armcm_irq.c index 1831009..c490922 100644 --- a/src/generic/armcm_irq.c +++ b/src/generic/armcm_irq.c @@ -6,6 +6,7 @@ #include "board/internal.h" // __CORTEX_M #include "irq.h" // irqstatus_t +#include "sched.h" // DECL_SHUTDOWN void irq_disable(void) @@ -71,3 +72,4 @@ clear_active_irq(void) "1:\n" : "=&r"(temp) : "r"(psr), "r"(0xfffffff9) : "r12", "cc"); } +DECL_SHUTDOWN(clear_active_irq); diff --git a/src/generic/canbus.c b/src/generic/canbus.c index dc50ea4..ebe5d15 100644 --- a/src/generic/canbus.c +++ b/src/generic/canbus.c @@ -10,6 +10,7 @@ #include "byteorder.h" // cpu_to_le32 #include "canbus.h" // canbus_set_uuid #include "canboot_main.h" +#include "sched.h" // sched_wake_task static uint32_t canbus_assigned_id; static uint8_t canbus_uuid[CANBUS_UUID_LEN]; @@ -19,7 +20,7 @@ static uint8_t canbus_uuid[CANBUS_UUID_LEN]; * Data transmission over CAN ****************************************************************/ -static volatile uint8_t canbus_tx_wake; +static struct task_wake canbus_tx_wake; static uint8_t transmit_buf[96], transmit_pos, transmit_max; uint8_t @@ -31,15 +32,14 @@ canbus_tx_clear(void) void canbus_notify_tx(void) { - canbus_tx_wake = 1; + sched_wake_task(&canbus_tx_wake); } void canbus_tx_task(void) { - if (!canbus_tx_wake) + if (!sched_check_wake(&canbus_tx_wake)) return; - canbus_tx_wake = 0; uint32_t id = canbus_assigned_id; if (!id) { transmit_pos = transmit_max = 0; @@ -57,6 +57,7 @@ canbus_tx_task(void) } transmit_pos = tpos; } +DECL_TASK(canbus_tx_task); // Encode and transmit a "response" message void @@ -93,8 +94,8 @@ canboot_sendf(uint8_t* data, uint16_t size) // Available commands and responses #define CANBUS_CMD_QUERY_UNASSIGNED 0x00 -#define CANBUS_CMD_SET_NODEID_CANBOOT 0x11 -#define CANBUS_CMD_CLEAR_NODE_ID_CANBOOT 0x12 +#define CANBUS_CMD_SET_CANBOOT_NODEID 0x11 +#define CANBUS_CMD_CLEAR_CANBOOT_NODEID 0x12 #define CANBUS_RESP_NEED_NODEID 0x20 // Helper to verify a UUID in a command matches this chip's UUID @@ -118,7 +119,7 @@ can_process_query_unassigned(uint32_t id, uint32_t len, uint8_t *data) uint8_t send[8]; send[0] = CANBUS_RESP_NEED_NODEID; memcpy(&send[1], canbus_uuid, sizeof(canbus_uuid)); - send[7] = CANBUS_CMD_SET_NODEID_CANBOOT; + send[7] = CANBUS_CMD_SET_CANBOOT_NODEID; // Send with retry for (;;) { int ret = canbus_send(CANBUS_ID_ADMIN_RESP, 8, send); @@ -128,7 +129,7 @@ can_process_query_unassigned(uint32_t id, uint32_t len, uint8_t *data) } static void -can_process_clear_node_id(void) +can_process_clear_canboot_nodeid(void) { canbus_assigned_id = 0; canbus_set_filter(canbus_assigned_id); @@ -143,7 +144,7 @@ can_id_conflict(void) } static void -can_process_set_nodeid(uint32_t id, uint32_t len, uint8_t *data) +can_process_set_canboot_nodeid(uint32_t id, uint32_t len, uint8_t *data) { if (len < 8) return; @@ -168,11 +169,11 @@ can_process(uint32_t id, uint32_t len, uint8_t *data) case CANBUS_CMD_QUERY_UNASSIGNED: can_process_query_unassigned(id, len, data); break; - case CANBUS_CMD_SET_NODEID_CANBOOT: - can_process_set_nodeid(id, len, data); + case CANBUS_CMD_SET_CANBOOT_NODEID: + can_process_set_canboot_nodeid(id, len, data); break; - case CANBUS_CMD_CLEAR_NODE_ID_CANBOOT: - can_process_clear_node_id(); + case CANBUS_CMD_CLEAR_CANBOOT_NODEID: + can_process_clear_canboot_nodeid(); break; } } @@ -182,7 +183,13 @@ can_process(uint32_t id, uint32_t len, uint8_t *data) * CAN packet reading ****************************************************************/ -static volatile uint8_t canbus_rx_wake; +static struct task_wake canbus_rx_wake; + +void +canbus_notify_rx(void) +{ + sched_wake_task(&canbus_rx_wake); +} // Handle incoming data (called from IRQ handler) void @@ -194,19 +201,12 @@ canbus_process_data(uint32_t id, uint32_t len, uint8_t *data) canbus_notify_rx(); } -void -canbus_notify_rx(void) -{ - canbus_rx_wake = 1; -} - // Task to process incoming commands and admin messages void canbus_rx_task(void) { - if (!canbus_rx_wake) + if (!sched_check_wake(&canbus_rx_wake)) return; - canbus_rx_wake = 0; // Read any pending CAN packets for (;;) { @@ -221,6 +221,8 @@ canbus_rx_task(void) can_process(id, ret, data); } } +DECL_TASK(canbus_rx_task); + /**************************************************************** * Setup and shutdown @@ -248,3 +250,4 @@ canbus_shutdown(void) canbus_notify_tx(); canbus_notify_rx(); } +DECL_SHUTDOWN(canbus_shutdown); diff --git a/src/generic/canbus.h b/src/generic/canbus.h index 9634e79..8d4a1d5 100644 --- a/src/generic/canbus.h +++ b/src/generic/canbus.h @@ -12,15 +12,12 @@ int canbus_read(uint32_t *id, uint8_t *data); int canbus_send(uint32_t id, uint32_t len, uint8_t *data); void canbus_set_filter(uint32_t id); void canbus_reboot(void); -void can_init(void); // canbus.c void canbus_notify_tx(void); void canbus_notify_rx(void); void canbus_process_data(uint32_t id, uint32_t len, uint8_t *data); void canbus_set_uuid(void *data); -void canbus_tx_task(void); -void canbus_rx_task(void); uint8_t canbus_tx_clear(void); #endif // canbus.h diff --git a/src/led.c b/src/led.c index 5743402..a95a180 100644 --- a/src/led.c +++ b/src/led.c @@ -9,6 +9,7 @@ #include "board/misc.h" // timer_read_time #include "ctr.h" // DECL_CTR #include "led.h" // check_blink_time +#include "sched.h" // DECL_INIT DECL_CTR("DECL_LED_PIN " __stringify(CONFIG_STATUS_LED_PIN)); extern uint32_t led_gpio, led_gpio_high; // Generated by buildcommands.py @@ -27,6 +28,7 @@ led_init(void) udelay(10); last_blink_time = timer_read_time(); } +DECL_INIT(led_init); void check_blink_time(uint32_t usec) diff --git a/src/led.h b/src/led.h index c9297b1..14b7403 100644 --- a/src/led.h +++ b/src/led.h @@ -1,7 +1,6 @@ #ifndef __LED_H #define __LED_H -void led_init(); void check_blink_time(uint32_t usec); #endif // led.h diff --git a/src/sched.c b/src/sched.c new file mode 100644 index 0000000..f82a97b --- /dev/null +++ b/src/sched.c @@ -0,0 +1,41 @@ +// Basic scheduling functions and startup code +// +// Copyright (C) 2016-2022 Kevin O'Connor +// +// This file may be distributed under the terms of the GNU GPLv3 license. + +#include "board/io.h" // readb +#include "sched.h" // sched_check_periodic + +// Note that a task is ready to run +void +sched_wake_task(struct task_wake *w) +{ + writeb(&w->wake, 1); +} + +// Check if a task is ready to run (as indicated by sched_wake_task) +uint8_t +sched_check_wake(struct task_wake *w) +{ + if (!readb(&w->wake)) + return 0; + writeb(&w->wake, 0); + return 1; +} + +void +sched_run_init(void) +{ + // Run all init functions marked with DECL_INIT() + extern void ctr_run_initfuncs(void); + ctr_run_initfuncs(); +} + +void +sched_run_tasks(void) +{ + // Run all task functions marked with DECL_TASK() + extern void ctr_run_taskfuncs(void); + ctr_run_taskfuncs(); +} diff --git a/src/sched.h b/src/sched.h new file mode 100644 index 0000000..6baa84b --- /dev/null +++ b/src/sched.h @@ -0,0 +1,29 @@ +#ifndef __SCHED_H +#define __SCHED_H + +#include // uint32_t +#include "ctr.h" // DECL_CTR + +// Declare an init function (called at firmware startup) +#define DECL_INIT(FUNC) _DECL_CALLLIST(ctr_run_initfuncs, FUNC) +// Declare a task function (called periodically during normal runtime) +#define DECL_TASK(FUNC) _DECL_CALLLIST(ctr_run_taskfuncs, FUNC) +// Declare a shutdown function (called on an emergency stop) +#define DECL_SHUTDOWN(FUNC) _DECL_CALLLIST(ctr_run_shutdownfuncs, FUNC) + +// Task waking struct +struct task_wake { + uint8_t wake; +}; + +// sched.c +void sched_wake_task(struct task_wake *w); +uint8_t sched_check_wake(struct task_wake *w); +void sched_run_init(void); +void sched_run_tasks(void); + +// Compiler glue for DECL_X macros above. +#define _DECL_CALLLIST(NAME, FUNC) \ + DECL_CTR("_DECL_CALLLIST " __stringify(NAME) " " __stringify(FUNC)) + +#endif // sched.h diff --git a/src/stm32/can.c b/src/stm32/can.c index 2533f24..8316195 100644 --- a/src/stm32/can.c +++ b/src/stm32/can.c @@ -13,7 +13,7 @@ #include "generic/armcm_boot.h" // armcm_enable_irq #include "generic/canbus.h" // canbus_notify_tx #include "internal.h" // enable_pclock -#include "ctr.h" // DECL_CONSTANT_STR +#include "sched.h" // DECL_INIT #if CONFIG_STM32_CANBUS_PA11_PA12 || CONFIG_STM32_CANBUS_PA11_PA12_REMAP DECL_CONSTANT_STR("RESERVE_PINS_CAN", "PA11,PA12"); @@ -317,3 +317,4 @@ can_init(void) uint64_t hash = fasthash64((uint8_t*)UID_BASE, 12, 0xA16231A7); canbus_set_uuid(&hash); } +DECL_INIT(can_init);