| @@ -0,0 +1,173 @@ | |||
| /*- | |||
| * SPDX-License-Identifier: BSD-2-Clause-FreeBSD | |||
| * | |||
| * Copyright (c) 1999 John D. Polstra | |||
| * Copyright (c) 1999,2001 Peter Wemm <peter@FreeBSD.org> | |||
| * 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 <sys/cdefs.h> | |||
| /* 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_ */ | |||
| @@ -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 \ | |||
| @@ -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 | |||
| @@ -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> | |||
| @@ -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 <usbd_cdc_if.h> | |||
| #include <misc.h> | |||
| #include <stdbool.h> | |||
| #include <stdint.h> | |||
| #include <string.h> | |||
| #include <sysinit.h> | |||
| 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; | |||
| } | |||
| @@ -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 <stdbool.h> | |||
| #include <stdint.h> | |||
| #include <stdlib.h> | |||
| #include <sysinit.h> | |||
| 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 | |||
| } | |||
| } | |||
| @@ -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 <linker_set.h> | |||
| /* 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_ */ | |||