From ac1a5177b4594302779387d05afce50f2ff660d9 Mon Sep 17 00:00:00 2001 From: John-Mark Gurney Date: Fri, 4 Feb 2022 02:34:33 -0800 Subject: [PATCH] add framework to get things started... --- linker_set.h | 173 +++++++++++++++++++++++ mk/boards.mk | 42 +++++- mk/mu.opts.mk | 4 +- rs485hid/Makefile | 39 +++++ rs485hid/rs485gw.c | 346 +++++++++++++++++++++++++++++++++++++++++++++ sysinit.c | 120 ++++++++++++++++ sysinit.h | 115 +++++++++++++++ 7 files changed, 834 insertions(+), 5 deletions(-) create mode 100644 linker_set.h create mode 100644 rs485hid/Makefile create mode 100644 rs485hid/rs485gw.c create mode 100644 sysinit.c create mode 100644 sysinit.h diff --git a/linker_set.h b/linker_set.h new file mode 100644 index 0000000..cdd96c4 --- /dev/null +++ b/linker_set.h @@ -0,0 +1,173 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 1999 John D. Polstra + * Copyright (c) 1999,2001 Peter Wemm + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. + * + * $FreeBSD$ + */ + +#ifndef _SYS_LINKER_SET_H_ +#define _SYS_LINKER_SET_H_ + +#include +/* START cdefs.h direct import from FreeBSD */ +/* This section has the follwing copyright */ +/*- + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Berkeley Software Design, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of the University 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 REGENTS 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 REGENTS 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. + * + * @(#)cdefs.h 8.8 (Berkeley) 1/9/95 + * $FreeBSD$ + */ + +#define __CONCAT1(x,y) x ## y +#define __CONCAT(x,y) __CONCAT1(x,y) +#define __STRING(x) #x /* stringify without expanding x */ +#define __XSTRING(x) __STRING(x) /* expand x, then stringify */ +#define __nosanitizeaddress +#define __nosanitizememory +#define __used __attribute__((__used__)) +#define __weak_symbol __attribute__((__weak__)) + +/* END cdefs.h direct import */ + +/* + * The following macros are used to declare global sets of objects, which + * are collected by the linker into a `linker_set' as defined below. + * For ELF, this is done by constructing a separate segment for each set. + */ + +#if defined(__powerpc64__) && (!defined(_CALL_ELF) || _CALL_ELF == 1) +/* + * ELFv1 pointers to functions are actaully pointers to function + * descriptors. + * + * Move the symbol pointer from ".text" to ".data" segment, to make + * the GCC compiler happy: + */ +#define __MAKE_SET_CONST +#else +#define __MAKE_SET_CONST const +#endif + +/* + * Private macros, not to be used outside this header file. + */ +#ifdef __GNUCLIKE___SECTION + +/* + * The userspace address sanitizer inserts redzones around global variables, + * violating the assumption that linker set elements are packed. + */ +#ifdef _KERNEL +#define __NOASAN +#else +#define __NOASAN __nosanitizeaddress +#endif + +#define __MAKE_SET_QV(set, sym, qv) \ + void *__WEAK(__CONCAT(__start_set_,set)); \ + void *__WEAK(__CONCAT(__stop_set_,set)); \ + static void const * qv \ + __NOASAN \ + __set_##set##_sym_##sym __section("set_" #set) \ + __used = &(sym) +#define __MAKE_SET(set, sym) __MAKE_SET_QV(set, sym, __MAKE_SET_CONST) +#else /* !__GNUCLIKE___SECTION */ +#error this file needs to be ported to your compiler +#endif /* __GNUCLIKE___SECTION */ + +/* + * Public macros. + */ +#define TEXT_SET(set, sym) __MAKE_SET(set, sym) +#define DATA_SET(set, sym) __MAKE_SET(set, sym) +#define DATA_WSET(set, sym) __MAKE_SET_QV(set, sym, ) +#define BSS_SET(set, sym) __MAKE_SET(set, sym) +#define ABS_SET(set, sym) __MAKE_SET(set, sym) +#define SET_ENTRY(set, sym) __MAKE_SET(set, sym) + +/* + * Initialize before referring to a given linker set. + */ +#define SET_DECLARE(set, ptype) \ + extern ptype __weak_symbol __section("set_" #set)*__CONCAT(__start_set_,set); \ + extern ptype __weak_symbol *__CONCAT(__stop_set_,set) __section("set_" #set) + +#define SET_BEGIN(set) \ + (&__CONCAT(__start_set_,set)) +#define SET_LIMIT(set) \ + (&__CONCAT(__stop_set_,set)) + +/* + * Iterate over all the elements of a set. + * + * Sets always contain addresses of things, and "pvar" points to words + * containing those addresses. Thus is must be declared as "type **pvar", + * and the address of each set item is obtained inside the loop by "*pvar". + */ +#define SET_FOREACH(pvar, set) \ + for (pvar = SET_BEGIN(set); pvar < SET_LIMIT(set); pvar++) + +#define SET_ITEM(set, i) \ + ((SET_BEGIN(set))[i]) + +/* + * Provide a count of the items in a set. + */ +#define SET_COUNT(set) \ + (SET_LIMIT(set) - SET_BEGIN(set)) + +#endif /* _SYS_LINKER_SET_H_ */ diff --git a/mk/boards.mk b/mk/boards.mk index 57a2cb5..ee226b2 100644 --- a/mk/boards.mk +++ b/mk/boards.mk @@ -1,6 +1,10 @@ SRCS.NODE151+= board.c SRCS.NODE151+= misc.c +_SRCTOPDIR:= $(.PARSEDIR)/.. +SRCTOP?=$(_SRCTOPDIR:tA) +STM32?=$(SRCTOP)/stm32 + ARMOBJDUMP?= arm-none-eabi-objdump ARMCC?= arm-none-eabi-gcc @@ -10,17 +14,22 @@ ARMCC?= arm-none-eabi-gcc .include <$(.PARSEDIR)/mu.opts.mk> +.if ${MK_SYSINIT} == "yes" +.PATH: $(SRCTOP) +SRCS+= sysinit.c +.endif + # Strobe .if ${MK_STROBE} == "yes" -.PATH: $(.CURDIR)/strobe -CFLAGS+= -I$(.CURDIR)/strobe -DSTROBE_SINGLE_THREAD=1 +.PATH: $(SRCTOP)/strobe +CFLAGS+= -I$(SRCTOP)/strobe -DSTROBE_SINGLE_THREAD=1 STROBE_SRCS+= strobe.c \ x25519.c .endif # LoRamac (SX1276) radio code .if ${MK_SX1276} == "yes" -LORAMAC_SRC = $(.CURDIR)/loramac/src +LORAMAC_SRC = $(SRCTOP)/loramac/src .PATH: $(LORAMAC_SRC)/radio/sx1276 $(LORAMAC_SRC)/system $(LORAMAC_SRC)/boards/mcu $(LORAMAC_SRC)/boards/NucleoL152 CFLAGS+= -I$(LORAMAC_SRC)/boards CFLAGS+= -I$(LORAMAC_SRC)/system @@ -32,12 +41,37 @@ SRCS+= adc.c timer.c delay.c gpio.c uart.c fifo.c SRCS+= adc-board.c delay-board.c gpio-board.c rtc-board.c lpm-board.c sx1276mb1las-board.c spi-board.c uart-board.c .endif +# Generic STM32F103 Microcontroller +.if ${MK_STM32F103} == "yes" + +ARMTARGET?= -mcpu=cortex-m3 -mthumb + +.PATH: $(STM32)/f103c8t6 +LINKER_SCRIPT=$(STM32)/f103c8t6/STM32F103C8T6_FLASH.ld + +SRCS+= \ + startup_stm32f103xb.s \ + stm32f1xx_hal.c \ + stm32f1xx_hal_cortex.c \ + stm32f1xx_hal_gpio.c \ + stm32f1xx_hal_pcd.c \ + stm32f1xx_hal_pcd_ex.c \ + stm32f1xx_ll_usb.c \ + system_stm32f1xx.c + +CFLAGS+= -I$(STM32) +CFLAGS+= -I$(STM32)/f103c8t6 +CFLAGS+= -DSTM32F103xB +.endif + # NODE151 Microcontroller .if ${MK_NODE151} == "yes" + ARMTARGET?= -mcpu=cortex-m3 -mthumb -STM32=$(.CURDIR)/stm32 + .PATH: $(STM32)/l151ccux LINKER_SCRIPT=$(STM32)/l151ccux/STM32L151CCUX_FLASH.ld + SRCS+= \ startup_stm32l151ccux.s \ stm32l1xx_hal.c \ diff --git a/mk/mu.opts.mk b/mk/mu.opts.mk index 3e5f4e1..3725966 100644 --- a/mk/mu.opts.mk +++ b/mk/mu.opts.mk @@ -3,10 +3,12 @@ # # See bsd.mkopt.mk for more information. -__DEFAULT_YES_OPTIONS = STROBE +__DEFAULT_YES_OPTIONS = STROBE \ + SYSINIT __DEFAULT_NO_OPTIONS = \ NODE151 \ + STM32F103 \ SX1276 \ USB_CDC diff --git a/rs485hid/Makefile b/rs485hid/Makefile new file mode 100644 index 0000000..0a5f365 --- /dev/null +++ b/rs485hid/Makefile @@ -0,0 +1,39 @@ +# Copyright 2022 John-Mark Gurney. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. 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. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. +# + +PROGS = rs485gw # lora.irr + +SRCS.rs485gw = rs485gw.c +SRCS.rs485gw+= misc.c + +.PATH: $(.CURDIR)/.. + +CFLAGS += -I$(.CURDIR)/.. + +WITH_STM32F103 = yes +WITH_USB_CDC = yes + +.include <../mk/boards.mk> + +.include <../mk/mu.progs.mk> diff --git a/rs485hid/rs485gw.c b/rs485hid/rs485gw.c new file mode 100644 index 0000000..69b5472 --- /dev/null +++ b/rs485hid/rs485gw.c @@ -0,0 +1,346 @@ +/*- + * Copyright 2022 John-Mark Gurney. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. + * + */ + +#include + +#include + +#include +#include +#include + +#include + +SYSINIT(hal_init, SI_SUB_HAL, SI_ORDER_FIRST, (void (*)(const void *))HAL_Init, NULL); + +void +clkenable(const void *none) +{ + GPIO_InitTypeDef GPIO_InitStruct; + + __HAL_RCC_GPIOB_CLK_ENABLE(); + __HAL_RCC_GPIOC_CLK_ENABLE(); + + GPIO_InitStruct = (GPIO_InitTypeDef){ + .Pin = GPIO_PIN_13, + .Mode = GPIO_MODE_OUTPUT_PP, + .Pull = GPIO_NOPULL, + .Speed = GPIO_SPEED_FREQ_LOW, + }; + HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); + + HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_RESET); +} +SYSINIT(clkenable, SI_SUB_HAL, SI_ORDER_SECOND, clkenable, NULL); + +void +oscconfig(const void *none) +{ + RCC_ClkInitTypeDef clkinitstruct; + RCC_OscInitTypeDef oscinitstruct; + RCC_PeriphCLKInitTypeDef rccperiphclkinit; + + + __HAL_RCC_PWR_CLK_ENABLE(); + + oscinitstruct = (RCC_OscInitTypeDef){ + .OscillatorType = RCC_OSCILLATORTYPE_HSE, + .HSEState = RCC_HSE_ON, + .HSEPredivValue = RCC_HSE_PREDIV_DIV1, + .PLL.PLLMUL = RCC_PLL_MUL9, + + .PLL.PLLState = RCC_PLL_ON, + .PLL.PLLSource = RCC_PLLSOURCE_HSE, + }; + + HAL_RCC_OscConfig(&oscinitstruct); + + /* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2 + * clocks dividers */ + clkinitstruct.ClockType = RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | + RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2; + + clkinitstruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; + clkinitstruct.AHBCLKDivider = RCC_SYSCLK_DIV1; + clkinitstruct.APB1CLKDivider = RCC_HCLK_DIV2; + clkinitstruct.APB2CLKDivider = RCC_HCLK_DIV1; + HAL_RCC_ClockConfig(&clkinitstruct, FLASH_LATENCY_2); + + + /* USB clock selection */ + rccperiphclkinit = (RCC_PeriphCLKInitTypeDef){ + .PeriphClockSelection = RCC_PERIPHCLK_USB, + .UsbClockSelection = RCC_USBCLKSOURCE_PLL_DIV1_5, + }; + HAL_RCCEx_PeriphCLKConfig(&rccperiphclkinit); + + /* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2 + clocks dividers */ + clkinitstruct = (RCC_ClkInitTypeDef){ + .ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2), + .SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK, + .AHBCLKDivider = RCC_SYSCLK_DIV1, + .APB1CLKDivider = RCC_HCLK_DIV2, + .APB2CLKDivider = RCC_HCLK_DIV1, + }; + HAL_RCC_ClockConfig(&clkinitstruct, FLASH_LATENCY_2); +} +SYSINIT(oscconfig, SI_SUB_HAL, SI_ORDER_THIRD, oscconfig, NULL); + +char * +findeol(char *pos, size_t len) +{ + + while (len) { + if (*pos == '\r' || *pos == '\n') + return pos; + pos++; + len--; + } + + return NULL; +} + +void +hexdump(const uint8_t *ptr, size_t len) +{ + int i; + + for (i = 0; i < len; i++) + usb_printf("%02x", ptr[i]); +} + +void +txdone(void) +{ + + usb_printf("txdone\r\n"); + //Radio.Rx(0); +} + +void +txtimeout(void) +{ + + usb_printf("txtimeout\r\n"); +} + +void +rxdone(uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr) +{ + + usb_printf("rxdone: size: %hu, rssi: %hd, snr: %d\r\ndata: ", size, rssi, snr); + hexdump(payload, size); + usb_printf("\r\n"); +} + +void +rxtimeout(void) +{ + + usb_printf("rxtimeout\r\n"); +} + +void +rxerr(void) +{ + usb_printf("rxerr\r\n"); +} + +static uint8_t +hexchartonib(char s) +{ + + switch (s) { + case '0'...'9': + return s - '0'; + case 'a'...'f': + return s - 'a' + 10; + case 'A'...'F': + return s - 'A' + 10; + default: + return -1; + } +} + +static bool +hexdecode(char *buf, size_t len, uint8_t *out) +{ + uint8_t topchr, botchr; + + if (len % 2) + return false; + + /* NB: only needed to silence a bad gcc warning */ + topchr = -1; + + while (len) { + if (len % 2) { + /* bottom nibble */ + botchr = hexchartonib(*buf); + if (topchr == -1 || botchr == -1) + return false; + + *out = topchr << 4 | botchr; + out++; + } else { + /* top nibble */ + topchr = hexchartonib(*buf); + } + len--; + buf++; + } + + return true; +} + +static const char pktstart[] = "pkt:"; +static const size_t pktstartlen = sizeof pktstart - 1; +static uint8_t pktbuf[128]; + +static void +process_line(char *start, char *end) +{ + size_t len; + + /* trim off leading CR/NL */ + while (start < end && (*start == '\r' || *start == '\n')) + start++; + + len = end - start; + + if (len >= pktstartlen && memcmp(start, pktstart, sizeof pktstart - 1) == 0) { + start += pktstartlen; + len -= pktstartlen; + + if (len % 2) { + usb_printf("invalid pkt len\r\n"); + return; + } + if (!hexdecode(start, len, pktbuf)) { + usb_printf("invalid pkt\r\n"); + return; + } + //Radio.Send(pktbuf, len / 2); + return; + } + usb_printf("line: %.*s", end - start, start); + fflush(vcp_usb); +} + +int +main(void) +{ + + //debug_printf("starting...\n"); + + //clkenable(NULL); + sysinit_run(); + + //Radio.Init(&revents); + + setlinebuf(vcp_usb); + +#if 1 + wait_for_vcp(); + + /* + * This is required to use w/ FreeBSD. This is an issue w/ the + * STM32 Core USB library: + * https://github.com/STMicroelectronics/STM32CubeL1/issues/10 + */ + HAL_Delay(50); + usb_printf("starting...\r\n"); + +#endif + + uint32_t v; + + char inpbuf[1024]; + char *lastcheck; + char *endchr; + int inpbufpos = 0; + int cpylen; + +loop: + //BoardLowPowerHandler(); + + /* while we have data */ + while (CDC_RX_LEN) { + /* store last position */ + lastcheck = &inpbuf[inpbufpos]; + + /* calculate how much space left */ + cpylen = MIN(sizeof inpbuf - inpbufpos, CDC_RX_LEN); + + /* copy into buffer */ + memcpy(&inpbuf[inpbufpos], CDC_RX_BUFFER, cpylen); + + /* and point to end of buffer */ + inpbufpos += cpylen; + + do { + /* find first end of line characters */ + endchr = findeol(lastcheck, cpylen); + + if (endchr != NULL) { + /* if so, process it */ + process_line(inpbuf, endchr); + + /* skip end of line char */ + endchr++; + + /* move remaining buffer to the beginning */ + memmove(inpbuf, endchr, inpbufpos - (endchr - inpbuf)); + + /* and store new length */ + inpbufpos = inpbufpos - (endchr - inpbuf); + + /* mark begining of stream as last checked */ + lastcheck = inpbuf; + + /* and try to process another line */ + continue; + } else if (inpbufpos == sizeof inpbuf) { + /* we overflowed the buffer */ + /* XXX - best way is to throw away this line */ + inpbufpos = 0; + } + } while (0); + + /* if we copied all the data */ + if (cpylen == CDC_RX_LEN) { + /* declare that we are ready to receive more data */ + CDC_RX_LEN = 0; + USBD_CDC_ReceivePacket(&hUsbDeviceFS); + } else { + /* if not, move the remaining to the begining and try again */ + memmove(CDC_RX_BUFFER, &CDC_RX_BUFFER[cpylen], CDC_RX_LEN - cpylen); + CDC_RX_LEN -= cpylen; + } + } + goto loop; +} diff --git a/sysinit.c b/sysinit.c new file mode 100644 index 0000000..bb81f13 --- /dev/null +++ b/sysinit.c @@ -0,0 +1,120 @@ +/*- + * Copyright 2022 John-Mark Gurney. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. + * + */ + +#include +#include +#include +#include + +SET_DECLARE(sysinit_set, struct sysinit); + +void +sysinit_run(void) +{ + const int cnt = SET_COUNT(sysinit_set); + uint16_t *idxarray = alloca(sizeof(uint16_t) * cnt); +#if defined(VERBOSE_SYSINIT) + uint16_t last; + bool verbose; +#endif + int i; + + for (i = 0; i < cnt; i++) + idxarray[i] = i; + + /* + * following mostly copied from FreeBSD sys/kern/init_main.c + * which has license: + * SPDX-License-Identifier: BSD-4-Clause + * + * Copyright (c) 1995 Terrence R. Lambert + * All rights reserved. + * + * Copyright (c) 1982, 1986, 1989, 1991, 1992, 1993 + * The Regents of the University of California. All rights reserved. + * (c) UNIX System Laboratories, Inc. + * + * as copying this to RAM might be expensive, use a stack + * allocated indirection array to do the sorting instead. + */ + uint16_t *sipp; + uint16_t *xipp; + uint16_t save; + + /* + * Perform a bubble sort of the system initialization objects by + * their subsystem (primary key) and order (secondary key). + */ +#define GI(x) (SET_BEGIN(sysinit_set)[(x)]) +#define GI_SUBSYSORDER(x) (GI((x))->si_subsys_order) +#define GI_SUBSYS(x) (GET_SUBSYS(GI_SUBSYSORDER(x))) +#define GI_ORDER(x) (GET_ORDER(GI_SUBSYSORDER(x))) + + for (sipp = &idxarray[0]; sipp < &idxarray[cnt]; sipp++) { + for (xipp = sipp + 1; xipp < &idxarray[cnt]; xipp++) { + if (GI_SUBSYS(*sipp) < GI_SUBSYS(*xipp) || + (GI_SUBSYS(*sipp) == GI_SUBSYS(*xipp) && + GI_ORDER(*sipp) <= GI_ORDER(*xipp))) + continue; /* skip*/ + save = *sipp; + *sipp = *xipp; + *xipp = save; + } + } + +#if defined(VERBOSE_SYSINIT) + last = SI_SUB_COPYRIGHT; + verbose = 0; +#endif + /* + * Traverse the (now) ordered list of system initialization tasks. + * Perform each task, and continue on to the next task. + */ + for (sipp = &idxarray[0]; sipp < &idxarray[cnt]; sipp++) { + if (GI_SUBSYS(*sipp) == SI_SUB_DUMMY) + continue; /* skip dummy task(s)*/ + +#if defined(VERBOSE_SYSINIT) + if (GI_SUBSYS(*sipp) > last && verbose_sysinit != 0) { + verbose = 1; + last = GI_SUBSYS(*sipp); + printf("subsystem %x\n", last); + } + if (verbose) { + printf(" %p(%p)... ", GI(*sipp)->func, + GI(*sipp)->udata); + } +#endif + + /* Call function */ + (GI(*sipp)->si_func)(GI(*sipp)->si_udata); + +#if defined(VERBOSE_SYSINIT) + if (verbose) + printf("done.\n"); +#endif + } +} diff --git a/sysinit.h b/sysinit.h new file mode 100644 index 0000000..fcc4f8a --- /dev/null +++ b/sysinit.h @@ -0,0 +1,115 @@ +/*- + * SPDX-License-Identifier: BSD-4-Clause + * + * Copyright (c) 1995 Terrence R. Lambert + * Copyright 2022 John-Mark Gurney + * All rights reserved. + * + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * (c) UNIX System Laboratories, Inc. + * All or some portions of this file are derived from material licensed + * to the University of California by American Telephone and Telegraph + * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * the permission of UNIX System Laboratories, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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. + * + * @(#)kernel.h 8.3 (Berkeley) 1/21/94 + * $FreeBSD$ + */ + +/* + * This system is similar to FreeBSD's SYSINIT(9), but w/ minor + * modifications. + */ + +#ifndef _SYSINIT_H_ +#define _SYSINIT_H_ 1 + +#include + +/* from FreeBSD sys/systm.h */ +#define CTASSERT(x) _Static_assert(x, "compile-time assertion failed") + +#define MAKE_SUBORDER(subsys, order) ((uint32_t)((subsys) << 16) | (order)) +#define GET_SUBSYS(x) (((x) >> 16) & 0xffff) +#define GET_ORDER(x) ((x) & 0xffff) + +enum sysinit_sub_id { + SI_SUB_DUMMY = 0x0000, /* not executed; for linker*/ + + SI_SUB_HAL = 0x0010, /* Early HAL init */ + SI_SUB_GPIO = 0x0030, /* Early GPIO */ + SI_SUB_CONSOLE = 0x0700, /* Setup console/debug prints */ + + SI_SUB_COPYRIGHT = 0x0800, /* start of when printf works */ + + SI_SUB_STANDARD = 0x8000, /* standard later initalization */ + + SI_SUB_LAST = 0xffff /* final initialization */ +}; + +/* + * Some enumerated orders; "ANY" sorts last. + */ +enum sysinit_elem_order { + SI_ORDER_FIRST = 0x0000, /* first*/ + SI_ORDER_SECOND = 0x0001, /* second*/ + SI_ORDER_THIRD = 0x0002, /* third*/ + SI_ORDER_FOURTH = 0x0003, /* fourth*/ + SI_ORDER_FIFTH = 0x0004, /* fifth*/ + SI_ORDER_SIXTH = 0x0005, /* sixth*/ + SI_ORDER_SEVENTH = 0x0006, /* seventh*/ + SI_ORDER_EIGHTH = 0x0007, /* eighth*/ + SI_ORDER_MIDDLE = 0x1000, /* somewhere in the middle */ + SI_ORDER_ANY = 0xffff /* last*/ +}; + +typedef void (*sysinit_cfunc_t)(const void *); + +struct sysinit { + uint32_t si_subsys_order; + sysinit_cfunc_t si_func; + const void *si_udata; +}; + +#define SYSINIT(uniquifier, subsystem, order, func, udata) \ + CTASSERT((subsystem & 0xffff) == subsystem); \ + CTASSERT((order & 0xffff) == order); \ + static struct sysinit uniquifier ## _sys_init = { \ + .si_subsys_order = MAKE_SUBORDER((subsystem), (order)), \ + .si_func = (func), \ + .si_udata = (udata), \ + }; \ + DATA_SET(sysinit_set,uniquifier ## _sys_init) + +void sysinit_run(void); + +#endif /* _SYSINIT_H_ */