Browse Source

add framework to get things started...

main
John-Mark Gurney 2 years ago
parent
commit
ac1a5177b4
7 changed files with 834 additions and 5 deletions
  1. +173
    -0
      linker_set.h
  2. +38
    -4
      mk/boards.mk
  3. +3
    -1
      mk/mu.opts.mk
  4. +39
    -0
      rs485hid/Makefile
  5. +346
    -0
      rs485hid/rs485gw.c
  6. +120
    -0
      sysinit.c
  7. +115
    -0
      sysinit.h

+ 173
- 0
linker_set.h View File

@@ -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_ */

+ 38
- 4
mk/boards.mk View File

@@ -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
- 1
mk/mu.opts.mk View File

@@ -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



+ 39
- 0
rs485hid/Makefile View File

@@ -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>

+ 346
- 0
rs485hid/rs485gw.c View File

@@ -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;
}

+ 120
- 0
sysinit.c View File

@@ -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
}
}

+ 115
- 0
sysinit.h View File

@@ -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_ */

Loading…
Cancel
Save