remove zephyr

This commit is contained in:
Peter McGoron 2023-06-14 15:17:23 -04:00
parent 41d7a88619
commit de970b5dd6
17 changed files with 0 additions and 1396 deletions

4
.gitmodules vendored
View File

@ -1,4 +0,0 @@
[submodule "creole"]
path = creole
url = https://software.mcgoron.com/peter/creole
branch = upsilon

1
creole

@ -1 +0,0 @@
Subproject commit 52279a9afc6afb3c589216e3f930e3d8d96dd119

View File

@ -1,21 +0,0 @@
cmake_minimum_required(VERSION 3.20.0)
# These must come BEFORE the zephyr package declaration.
set(DTC_OVERLAY_FILE "../firmware/overlay.dts")
set(BOARD "litex_vexriscv")
set(EXTRA_CFLAGS "-Wfatal-errors -Werror -Wno-error=unused-const-variable -Wno-error=unused-variable -Wno-error=unused-function")
include("../firmware/overlay.cmake")
find_package(Zephyr)
project(upsilon)
include_directories("../firmware")
include_directories("src/")
include_directories("../creole")
include_directories("../firmware/rtl/control_loop")
set_source_files_properties(src/main.c PROPERTIES COMPILE_FLAGS -DMAIN_LOG_LEVEL=4)
set_source_files_properties(../creole/creole.c PROPERTIES COMPILE_FLAGS -DCREOLE_LOG_LEVEL=4)
# Add all source files here.
target_sources(app PRIVATE src/access.c src/buf.c src/main.c src/sock.c ../creole/creole.c)
# target_sources(app PRIVATE src/tests/test_ethernet.c)

View File

@ -1,3 +0,0 @@
mainmenu "CryoSNOM 1"
source "Kconfig.zephyr"

View File

@ -1,13 +0,0 @@
unexport CXXFLAGS
unexport CFLAGS
unexport CPPFLAGS
unexport LDFLAGS
# TODO: Number of processors
build/zephyr/zephyr.bin: build/Makefile
cd build && make -j7
build/Makefile: ../creole/creole.c src/*.c ../firmware/overlay.dts ../firmware/pin_io.c prj.conf CMakeLists.txt
mkdir -p build
cd build && cmake ..
clean:
rm -rf build

View File

@ -1,42 +0,0 @@
K_SEM_DEFINE(dhcp_ready, 0, 1);
static bool
check_dhcp(struct net_if *iface)
{
// Scan IP addresses allocated for Unicast
for (int i = 0; i < NET_IF_MAX_IPV4_ADDR; i++) {
if (iface->config.ip.ipv4->unicast[i].addr_type != NET_ADDR_DHCP)
continue;
return true;
}
return false;
}
static void
dhcp_handler(struct net_mgmt_event_callback *cb,
uint32_t ev,
struct net_if *iface)
{
if (ev != NET_EVENT_IPV4_ADDR_ADD)
return;
if (check_dhcp(iface))
k_sem_give(&dhcp_ready);
}
static void
setup_dhcp(void)
{
static struct net_mgmt_event_callback cb;
net_mgmt_init_event_callback(&cb, dhcp_handler, NET_EVENT_IPV4_ADDR_ADD);
net_mgmt_add_event_callback(&cb);
struct net_if *iface = net_if_get_default();
if (!check_dhcp(iface)) {
net_dhcpv4_start(iface);
k_sem_take(&dhcp_ready, K_FOREVER);
}
}

View File

@ -1,29 +0,0 @@
CONFIG_LOG=y
CONFIG_NET_LOG=y
CONFIG_LOG_BUFFER_SIZE=1024
CONFIG_LOG_PRINTK=y
CONFIG_LOG_DEFAULT_LEVEL=3
CONFIG_NETWORKING=y
CONFIG_NET_IPV4=y
CONFIG_NET_IPV6=n
CONFIG_NET_TCP=y
CONFIG_NET_SOCKETS=y
CONFIG_NET_ARP=y
CONFIG_NET_UDP=y
CONFIG_NET_TCP_ISN_RFC6528=n
CONFIG_INIT_STACKS=y
CONFIG_THREAD_LOCAL_STORAGE=y
CONFIG_SCHED_SCALABLE=y
CONFIG_NET_CONFIG_SETTINGS=y
CONFIG_NET_CONFIG_NEED_IPV4=y
CONFIG_NET_MGMT=y
CONFIG_NET_MGMT_EVENT=y
# Ethernet config. Change me for your setup!
CONFIG_NET_DHCPV4=n
CONFIG_NET_CONFIG_MY_IPV4_ADDR="192.168.1.50"
CONFIG_NET_CONFIG_MY_IPV4_GW="192.168.1.1"
CONFIG_NET_CONFIG_MY_IPV4_NETMASK="255.255.255.0"

View File

@ -1,447 +0,0 @@
/* Verilog access control.
*
* Mutex management for hardware resources.
* Each mutex has a thread-local lock counter associated with it, since in
* Zephyr the recursive lock counter is not publically accessable.
*
* On the final unlock for a thread, the code will always take steps to
* reset the state of the Verilog module so that another thread will
* see a consistent start state.
*/
#include <zephyr/kernel.h>
#include <soc.h>
#include <zephyr/logging/log.h>
#include "upsilon.h"
#include "access.h"
#include "control_loop_cmds.h"
LOG_MODULE_REGISTER(access, 4);
#include "pin_io.c"
/* The values from converters are not aligned to 32 bits.
* These values are still in twos compliment and have to be
* manually sign-extended.
*/
static inline uint32_t
sign_extend(uint32_t in, unsigned len)
{
if (in >> (len - 1) & 1) {
uint32_t mask = (1 << len) - 1;
return ~mask | (in & mask);
} else {
return in;
}
}
/*********************
* DAC
*********************/
static struct k_mutex dac_mutex[DAC_MAX];
static __thread int dac_locked[DAC_MAX];
int
dac_take(int dac, k_timeout_t timeout)
{
if (dac < 0 || dac >= DAC_MAX)
return -EFAULT;
int e = k_mutex_lock(dac_mutex + dac, timeout);
if (e == 0) {
dac_locked[dac] += 1;
}
return e;
}
int
dac_release(int dac)
{
if (dac < 0 || dac >= DAC_MAX)
return -EFAULT;
if (dac_locked[dac] == 1) {
write_dac_arm(0, dac);
// TODO: Flush DAC?
// while (!read_dac_finished(dac));
}
int e = k_mutex_unlock(dac_mutex + dac);
if (e == 0) {
dac_locked[dac] -= 1;
}
return e;
}
int
dac_read_write(int dac, creole_word send, k_timeout_t timeout,
creole_word *recv)
{
int e = dac_take(dac, timeout);
if (e != 0)
return e;
dac_switch(dac, DAC_SPI_PORT, K_NO_WAIT);
write_to_dac(send, dac);
write_dac_arm(1, dac);
/* Non-recursive locks should busy wait. */
/* 10ns * (2 * 10 cycles per half DAC cycle)
* 24 bits
*/
if (dac_locked[dac] > 1)
k_sleep(K_NSEC(10*2*10*24));
while (!read_dac_finished(dac));
if (recv)
*recv = sign_extend(read_from_dac(dac), 20);
write_dac_arm(0, dac);
dac_release(dac);
return 0;
}
int
dac_switch(int dac, int setting, k_timeout_t timeout)
{
int e = dac_take(dac, timeout);
if (e != 0)
return e;
write_dac_sel(setting, dac);
dac_release(dac);
return 0;
}
/**********************
* adc read
*********************/
static struct k_mutex adc_mutex[ADC_MAX];
static __thread int adc_locked[ADC_MAX];
int
adc_take(int adc, k_timeout_t timeout)
{
if (adc < 0 || adc >= ADC_MAX)
return -EFAULT;
LOG_DBG("%s: taking adc %d", get_thread_name(), adc);
int e = k_mutex_lock(adc_mutex + adc, timeout);
LOG_DBG("%s: adc %d taken", get_thread_name(), adc);
if (e == 0) {
adc_locked[adc] += 1;
}
LOG_DBG("%s: adc %d lockeg", get_thread_name(), adc);
return e;
}
int
adc_release(int adc)
{
if (adc < 0 || adc >= ADC_MAX)
return -EFAULT;
LOG_DBG("%s: in adc_release", get_thread_name());
if (adc_locked[adc] == 1) {
write_adc_arm(0, adc);
// TODO: flush ADC?
}
int e = k_mutex_unlock(adc_mutex + adc);
if (e == 0) {
adc_locked[adc] -= 1;
}
return e;
}
int
adc_switch(int adc, int setting, k_timeout_t timeout)
{
/* As of now, only one ADC (the CLOOP adc) is used
* by two modules at the same time.
*/
if (adc != 0)
return -ENOENT;
int e = adc_take(adc, timeout);
if (e != 0)
return e;
write_adc_sel_0(setting);
adc_release(adc);
return 0;
}
int
adc_read(int adc, k_timeout_t timeout, creole_word *wrd)
{
int e;
if ((e = adc_take(adc, timeout)) != 0)
return e;
adc_switch(adc, ADC_SPI_PORT, K_NO_WAIT);
write_adc_arm(1, adc);
/* Recursive locks should busy wait. */
if (adc_locked[adc] > 1)
k_sleep(K_NSEC(550 + 24*2*10*10));
while (!read_adc_finished(adc));
*wrd = sign_extend(read_from_adc(adc), 20);
write_adc_arm(0, adc);
adc_release(adc);
return 0;
}
/********
* Control loop
*******/
static struct k_mutex cloop_mutex;
static __thread int cloop_locked;
int
cloop_take(k_timeout_t timeout)
{
int e = k_mutex_lock(&cloop_mutex, timeout);
if (e == 0) {
cloop_locked++;
}
return e;
}
int
cloop_release(void)
{
/* Do not attempt to reset the CLOOP interface.
* Other scripts will fight to modify the CLOOP constants
* while the loop is still running.
*/
int e = k_mutex_unlock(&cloop_mutex);
if (e == 0) {
cloop_locked--;
}
return e;
}
int
cloop_read(int code, uint32_t *high_reg, uint32_t *low_reg,
k_timeout_t timeout)
{
uint64_t v = 0;
if (cloop_take(timeout) != 0)
return 0;
write_cl_cmd(code);
write_cl_start_cmd(1);
while (!read_cl_finish_cmd());
v = read_cl_word_out();
write_cl_start_cmd(0);
*high_reg = v >> 32;
*low_reg = v & 0xFFFFFFFF;
cloop_release();
return 1;
}
int
cloop_write(int code, uint32_t high_val, uint32_t low_val,
k_timeout_t timeout)
{
if (cloop_take(timeout) != 0)
return 0;
write_cl_cmd(code);
write_cl_word_in((uint64_t) high_val << 32 | low_val);
write_cl_start_cmd(1);
while (!read_cl_finish_cmd());
write_cl_start_cmd(0);
cloop_release();
return 1;
}
/************
* Waveforms
***********/
static struct k_mutex waveform_mutex[DAC_MAX];
static __thread int waveform_locked[DAC_MAX];
int
waveform_take(int waveform, k_timeout_t timeout)
{
if (waveform < 0 || waveform >= DAC_MAX)
return -EFAULT;
int e = k_mutex_lock(waveform_mutex + waveform, timeout);
if (e == 0) {
waveform_locked[e]++;
}
return e;
}
static void
waveform_disarm_wait(int wf)
{
write_wf_arm(0, wf);
/* TODO: add wait */
while (read_wf_running(wf));
}
int
waveform_release(int waveform)
{
if (waveform < 0 || waveform >= DAC_MAX)
return -EFAULT;
if (waveform_locked[waveform] == 1) {
waveform_disarm_wait(waveform);
}
int e = k_mutex_unlock(waveform_mutex + waveform);
if (e == 0) {
waveform_locked[e]--;
}
return e;
}
size_t
creole_to_array(const struct creole_reader *start, creole_word *buf, size_t buflen)
{
size_t i = 0;
struct creole_word w;
struct creole_reader r = *start;
while (creole_decode(&r, &w) && i < buflen) {
buf[i++] = w.word;
}
return i;
}
int
waveform_load(uint32_t buf[MAX_WL_SIZE], int slot, k_timeout_t timeout)
{
if (waveform_take(slot, timeout) != 0)
return 0;
write_wf_start_addr((uint32_t) buf, slot);
write_wf_refresh_start(1, slot);
while (!read_wf_refresh_finished(slot));
write_wf_refresh_start(0, slot);
waveform_release(slot);
return 1;
}
int
waveform_halt_until_finished(int slot)
{
write_wf_halt_on_finish(1, slot);
while (!read_wf_finished(slot));
return 1;
}
int
waveform_arm(int slot, bool halt_on_finish, uint32_t wait, k_timeout_t timeout)
{
if (waveform_take(slot, timeout) != 0)
return 0;
if (dac_take(slot, timeout) != 0) {
waveform_release(slot);
return 0;
}
dac_switch(slot, DAC_WF_PORT, K_NO_WAIT);
write_wf_halt_on_finish(halt_on_finish, slot);
write_wf_time_to_wait(wait, slot);
write_wf_arm(1, slot);
return 1;
}
int
waveform_disarm(int slot)
{
waveform_disarm_wait(slot);
waveform_release(slot);
dac_release(slot);
return 1;
}
/**********
* Init and deinit
*********/
void
access_release_thread(void)
{
while (cloop_release() == 0)
cloop_locked--;
if (cloop_locked != 0) {
LOG_WRN("%s: cloop mutex counter mismatch", get_thread_name());
cloop_locked = 0;
}
for (int i = 0; i < DAC_MAX; i++) {
while (dac_release(i) == 0)
dac_locked[i]--;
if (dac_locked[i] != 0) {
LOG_WRN("%s: dac mutex %d counter mismatch", get_thread_name(), i);
dac_locked[i] = 0;
}
while (waveform_release(i) == 0)
waveform_locked[i]--;
if (waveform_locked[i] != 0) {
LOG_WRN("%s: waveform mutex %d counter mismatch", get_thread_name(), i);
waveform_locked[i] = 0;
}
}
for (int i = 0; i < ADC_MAX; i++) {
while (adc_release(i) == 0)
adc_locked[i]--;
if (adc_locked[i] != 0) {
LOG_WRN("%s: adc mutex %d counter mismatch", get_thread_name(), i);
adc_locked[i] = 0;
}
}
}
void
access_init(void)
{
LOG_INF("access_init");
if (k_mutex_init(&cloop_mutex) != 0) {
LOG_ERR("err: cloop mutex");
k_fatal_halt(K_ERR_KERNEL_PANIC);
}
for (int i = 0; i < DAC_MAX; i++) {
if (k_mutex_init(dac_mutex + i) != 0) {
LOG_ERR("err: dac mutex %d", i);
k_fatal_halt(K_ERR_KERNEL_PANIC);
}
if (k_mutex_init(waveform_mutex + i) != 0) {
LOG_ERR("err: waveform mutex %d", i);
k_fatal_halt(K_ERR_KERNEL_PANIC);
}
}
for (int i = 0; i < ADC_MAX; i++) {
if (k_mutex_init(adc_mutex + i) != 0) {
LOG_ERR("err: adc mutex %d", i);
k_fatal_halt(K_ERR_KERNEL_PANIC);
}
}
LOG_INF("access_init done");
}

View File

@ -1,46 +0,0 @@
#pragma once
#include <zephyr/kernel.h>
#include "creole.h"
int dac_take(int dac, k_timeout_t timeout);
int dac_release(int dac);
int dac_read_write(int dac, creole_word send, k_timeout_t timeout,
creole_word *recv);
/* These ports are defined in firmware/rtl/base/base.v.m4 */
#define DAC_SPI_PORT 0
#define DAC_WF_PORT 1
#define DAC_CLOOP_PORT 2
int dac_switch(int dac, int setting, k_timeout_t timeout);
int adc_take(int adc, k_timeout_t timeout);
int adc_release(int adc);
int adc_read(int adc, k_timeout_t timeout, creole_word *wrd);
#define ADC_SPI_PORT 0
#define ADC_CLOOP_PORT 1
int adc_switch(int adc, int setting, k_timeout_t timeout);
int cloop_take(k_timeout_t timeout);
int cloop_read(int code, uint32_t *high_reg, uint32_t *low_reg,
k_timeout_t timeout);
int cloop_write(int code, uint32_t high_val, uint32_t low_val,
k_timeout_t timeout);
int cloop_release(void);
int waveform_take(int waveform, k_timeout_t timeout);
int waveform_release(int waveform);
#define MAX_WL_SIZE 4096
int waveform_load(uint32_t buf[MAX_WL_SIZE], int slot, k_timeout_t timeout);
int waveform_arm(int slot, bool halt_on_finish, uint32_t wait, k_timeout_t timeout);
int waveform_disarm(int slot);
/* Zephyr OS does not automatically clean up mutex resources.
* This will release all held locks.
*/
void access_release_thread(void);
/* Called once on initializion. */
void access_init(void);

View File

@ -1,44 +0,0 @@
#include <zephyr/zephyr.h>
#include <zephyr/sys/printk.h>
#include "buf.h"
int
buf_writevf(struct bufptr *bp, const char *fmt, va_list va)
{
/* vsnprintk() returns the amount of bytes that would
* be stored in the buffer if the buffer was big enough,
* excluding the NUL terminator.
* The function will _always_ write a NUL terminator
* unless bp->left == 0.
*/
int w = vsnprintk(bp->p, bp->left, fmt, va);
if (w < 0)
return BUF_WRITE_ERR;
/* Return the number of bytes that are required to be
* written.
* Do not increment the buffer pointer, the truncated
* data may not be safe.
* Since w is the amount of required bytes minus the NUL
* terminator, w == bp->left is still an out-of-memory
* situation.
*/
if (w >= bp->left) {
return w - bp->left + 1;
} else {
bp->p += w;
bp->left -= w;
return BUF_OK;
}
}
int
buf_writef(struct bufptr *bp, const char *fmt, ...)
{
va_list va;
va_start(va, fmt);
int r = buf_writevf(bp, fmt, va);
va_end(va);
return r;
}

View File

@ -1,35 +0,0 @@
#pragma once
/* This is a pointer _into_ a buffer. It is incremented (and the variable
* "left" decremented) after each operation.
*
* Space is always left for a NUL terminator.
*/
struct bufptr {
char *p;
size_t left;
};
enum {
BUF_OK = 0,
BUF_WRITE_ERR = -1,
BUF_SOCK_ERR = -2
};
/* Write a formatted string to bp.
* This function uses printf(), which means that it deals with
* writing _C-strings_, not unterminated buffers.
* When using this function, the buffer must be _one more_ than
* the maximum message length. For instance, a 1024-byte message
* should be in a 1025-byte buffer. HOWEVER, bp->left must still
* be set to the total length of the buffer (in the example, 1025).
*
* The final bufptr points to the NUL terminator, so that it
* is overwritten on each call to the function.
*
* This function returns 0 for a successful write, -1 for an
* encoding error (should never happen), and a positive value
* for the amount of bytes that could not fit.
*/
int buf_writevf(struct bufptr *bp, const char *fmt, va_list va);
int buf_writef(struct bufptr *bp, const char *fmt, ...);

View File

@ -1,213 +0,0 @@
#include <zephyr/zephyr.h>
#include <errno.h>
#include <zephyr/net/socket.h>
#include <zephyr/kernel.h>
#include <zephyr/logging/log.h>
#include "upsilon.h"
#include "access.h"
#include "sock.h"
#include "buf.h"
LOG_MODULE_REGISTER(main, 4);
#define THREAD_STACK_SIZ 1024*32
#define THREADNUM 32
static K_KERNEL_STACK_ARRAY_DEFINE(stacks, THREADNUM, THREAD_STACK_SIZ);
#define READBUF_SIZ 0xFFFF
static unsigned char readbuf[THREADNUM][READBUF_SIZ];
static struct k_thread threads[THREADNUM];
static bool thread_ever_used[THREADNUM];
static const char *const compiler_ret_str[CREOLE_COMPILE_RET_LEN] = {
[CREOLE_COMPILE_OK] = "compile ok",
[CREOLE_OPCODE_READ_ERROR] = "opcode read error",
[CREOLE_OPCODE_MALFORMED] = "opcode malformed",
[CREOLE_ARG_READ_ERROR] = "arg read error",
[CREOLE_ARG_MALFORMED] = "arg malformed",
[CREOLE_LAST_READ_ERROR] = "last read error",
[CREOLE_LAST_MALFORMED] = "last malformed",
[CREOLE_DATA_OVERFLOW] = "data overflow",
[CREOLE_TYPE_ERROR] = "type error",
[CREOLE_PROGRAM_OVERFLOW] = "program overflow"
};
static const char *const run_ret_str[CREOLE_RUN_RET_LEN] = {
[CREOLE_STEP_CONTINUE] = "continue",
[CREOLE_STEP_SYSCALL] = "syscall",
[CREOLE_STEP_STOP] = "stop",
[CREOLE_STACK_OVERFLOW] = "overflow",
[CREOLE_STACK_UNDERFLOW] = "underflow",
[CREOLE_RUN_DECODE_ERROR] = "decode error",
[CREOLE_REGISTER_OVERFLOW] = "register overflow",
[CREOLE_STEP_UNKNOWN_OPCODE] = "unknown opcode",
[CREOLE_DIV_BY_ZERO] = "div by zero",
[CREOLE_STEP_HIGH_BIT_MALFORMED] = "high bit malformed",
[CREOLE_JUMP_OVERFLOW] = "jump overflow"
};
/* Returns 0 if the sock is still connected. */
static int
hup(int sock)
{
struct zsock_pollfd fd = {
.fd = sock,
.events = POLLHUP,
.revents = 0
};
return zsock_poll(&fd, 1, 0);
}
static void
exec_creole(unsigned char *buf, int size, int sock)
{
#define DATSLEN 64
struct creole_reader dats[DATSLEN];
#define REGLEN 32
creole_word reg[REGLEN];
#define STKLEN 1024
creole_word stk[STKLEN];
struct creole_env env = {
.dats = dats,
.datlen = DATSLEN,
.reg = reg,
.reglen = REGLEN,
.stk = stk,
.stklen = STKLEN,
.r_current = {buf, size},
.r_start = {buf, size},
.fd = sock
};
int e = creole_compile(&env);
if (e != CREOLE_COMPILE_OK) {
LOG_WRN("%s: compile: %s at %zu", get_thread_name(),
compiler_ret_str[e],
(env.r_start.left - env.r_current.left));
return;
}
for (;;) {
creole_word sc;
e = creole_step(&env, &sc);
LOG_DBG("%s: %s", get_thread_name(), run_ret_str[e]);
switch (e) {
case CREOLE_STEP_CONTINUE:
continue;
case CREOLE_STEP_SYSCALL:
LOG_WRN("%s: syscall unsupported", get_thread_name());
continue;
case CREOLE_STEP_STOP:
return;
default:
LOG_WRN("%s: run: %s", get_thread_name(),
run_ret_str[e]);
return;
}
if (hup(sock) != 0) {
LOG_WRN("%s: hangup", get_thread_name());
return;
}
}
}
/* Read the size of the message from the socket. */
static int
read_size(int s)
{
char buf[2];
struct bufptr bp = {buf, sizeof(buf)};
int e = sock_read_buf(s, &bp, true);
if (e != 0)
return e;
return (unsigned char)buf[0] | (unsigned char) buf[1] << 8;
}
/* Thread entry. Reads the program send by the connection and executes it. */
static void
exec_entry(void *client_p, void *connection_num_p,
void *threadnum_p)
{
intptr_t client = (intptr_t)client_p;
intptr_t connection_num = (intptr_t)connection_num_p;
intptr_t threadnum = (intptr_t)threadnum_p;
char thread_name[64];
snprintk(thread_name, sizeof(thread_name), "%"PRIdPTR":%"PRIdPTR, threadnum, connection_num);
k_thread_name_set(k_current_get(), thread_name);
LOG_DBG("%s: entered thread", get_thread_name());
int size = read_size(client);
if (size < 0) {
LOG_WRN("%s: error in read size: %d", get_thread_name(), size);
zsock_close(client);
return;
}
LOG_INF("%s: program length: %d", get_thread_name(), size);
struct bufptr bp = {readbuf[threadnum], size};
int e = sock_read_buf(client, &bp, true);
if (e != 0) {
LOG_WRN("%s: error in read body: %d", get_thread_name(), e);
zsock_close(client);
return;
}
LOG_DBG("%s: read program", get_thread_name());
exec_creole(readbuf[threadnum], size, (int)client);
zsock_close(client);
LOG_INF("Exiting thread %s", get_thread_name());
}
static void
main_loop(int srvsock)
{
static unsigned int connection_counter = 0;
for (;;) {
int client = server_accept_client(srvsock);
int i;
for (i = 0; i < THREADNUM; i++) {
if (!thread_ever_used[i] || k_thread_join(&threads[i], K_NO_WAIT) == 0) {
LOG_DBG("launching thread %d", i);
connection_counter++;
thread_ever_used[i] = true;
k_thread_create(&threads[i], stacks[i],
THREAD_STACK_SIZ, exec_entry,
(void*) client, (void*) connection_counter,
NULL, 1, 0, K_NO_WAIT);
break;
}
}
if (i == THREADNUM) {
LOG_INF("Too many connections (max %d)",
THREADNUM);
zsock_close(client);
}
}
}
/* For reproducible builds if needed */
#ifdef SOURCE_DATE_EPOCH
# define BUILD_TIME SOURCE_DATE_EPOCH
#else
# define BUILD_TIME __DATE__ " " __TIME__
#endif
void
main(void)
{
LOG_PRINTK("Upsilon on ZephyrOS, built on %s\n", BUILD_TIME);
access_init();
k_thread_name_set(k_current_get(), "main thread");
for (;;) {
int sock = server_init_sock(6626);
main_loop(sock);
zsock_close(sock);
}
}

View File

@ -1,135 +0,0 @@
#include <zephyr/zephyr.h>
#include <errno.h>
#include <zephyr/net/socket.h>
#include <zephyr/kernel.h>
#include <zephyr/logging/log.h>
#include "sock.h"
#include "buf.h"
LOG_MODULE_REGISTER(sock);
int
server_init_sock(int port)
{
int sock;
sock = zsock_socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sock < 0) {
LOG_ERR("error: socket: %d", sock);
k_fatal_halt(K_ERR_KERNEL_PANIC);
}
struct sockaddr_in addr = {
.sin_family = AF_INET,
.sin_addr = {.s_addr = htonl(INADDR_ANY)},
.sin_port = htons(port)
};
if (zsock_bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
LOG_ERR("error: bind: %d", errno);
k_fatal_halt(K_ERR_KERNEL_PANIC);
}
if (zsock_listen(sock, 5) < 0) {
LOG_ERR("error: listen: %d", errno);
k_fatal_halt(K_ERR_KERNEL_PANIC);
}
LOG_INF("Upsilon waiting on %d", port);
return sock;
}
int
server_accept_client(int server)
{
int client;
struct sockaddr_in addr;
socklen_t len = sizeof(addr);
/* Accept clients in a loop. This should block when there are no clients
* so other threads can run.
*/
do {
LOG_DBG("Accept");
/*
struct zsock_pollfd server_fd = { .fd = server, .events = ZSOCK_POLLIN };
zsock_poll(&server_fd, 1, -1);
*/
client = zsock_accept(server, (struct sockaddr *)&addr, &len);
if (client < 0)
LOG_WRN("error in accept: %d", errno);
} while (client < 0);
char ipaddr[32];
zsock_inet_ntop(addr.sin_family, &addr.sin_addr, ipaddr, sizeof(ipaddr));
LOG_INF("Connection received from %s", ipaddr);
return client;
}
int
sock_read_buf(int sock, struct bufptr *bp, bool entire)
{
do {
ssize_t l = zsock_recv(sock, bp->p, bp->left, 0);
if (l == 0)
return -ECONNRESET;
if (l < 0)
return -errno;
bp->left -= l;
bp->p += l;
} while (entire && bp->left > 0);
return 0;
}
int
sock_write_buf(int sock, struct bufptr *bp)
{
/* Since send may not send all data in the buffer at once,
* loop until it sends all data (or fails).
*/
while (bp->left) {
ssize_t l = zsock_send(sock, bp->p, bp->left, 0);
if (l == 0)
return -ECONNRESET;
if (l < 0)
return -errno;
bp->p += l;
bp->left -= l;
}
return 0;
}
int
sock_vprintf(int sock, struct bufptr *bp, const char *fmt, va_list va)
{
struct bufptr store_bp = *bp;
int r = buf_writevf(bp, fmt, va);
if (r != BUF_OK)
return r;
/* The difference between the initial and final values of
* `left` is the amount of bytes written to the buffer.
* Set left to this difference so that the only thing sent
* is the bytes written by buf_writevf.
*/
store_bp.left -= bp->left;
if (!sock_write_buf(sock, &store_bp)) {
return BUF_SOCK_ERR;
} else {
return BUF_OK;
}
}
int
sock_printf(int sock, struct bufptr *bp, const char *fmt, ...)
{
va_list va;
va_start(va, fmt);
bool b = sock_vprintf(sock, bp, fmt, va);
va_end(va);
return b;
}

View File

@ -1,29 +0,0 @@
#pragma once
#include <stdarg.h>
#include "buf.h"
/* Initialize server to listen on the port passed as an argument.
*/
int server_init_sock(int port);
/* Accept a client and allocate a file descriptor for the client.
*/
int server_accept_client(int server);
/* Read data into buffer. Returns 0 if buffer is filled. This is
* raw binary (no NUL termination).
*/
int sock_read_buf(int sock, struct bufptr *bp, bool entire);
/* Write raw buffer data into socket. This data is raw binary and
* does not have to be NUL terminated. Returns 0 when all data has
* been written.
*/
int sock_write_buf(int sock, struct bufptr *bp);
/* Write formatted string into socket. The user must provide a
* buffer into which the formatted string is written. These return
* with a buf.h error, or BUF_OK when successful.
*/
int sock_vprintf(int sock, struct bufptr *bp, const char *fmt, va_list va);
int sock_printf(int sock, struct bufptr *bp, const char *fmt, ...);

View File

@ -1,211 +0,0 @@
#include <zephyr/zephyr.h>
#include <zephyr/kernel.h>
#include <zephyr/logging/log.h>
#include <stdbool.h>
#include "pin_io.h"
#include "io.h"
LOG_MODULE_REGISTER(dac_adc_test_main);
#define ATTEMPTS 5
static bool dac_ready[DAC_MAX] = {0};
static void
init_dacs(void)
{
for (size_t i = 0; i < DAC_MAX; i++) {
for (int j = 0; j < ATTEMPTS; j++) {
if (dac_init(i)) {
LOG_INF("DAC #%zu initialized, attempt %d\n", i, j);
dac_ready[i] = 1;
break;
}
}
if (!dac_ready[i])
LOG_WRN("DAC #%zu disconnected!\n", i);
}
}
K_MUTEX_DEFINE(print_mutex);
static void
print_mutex_unlock_impl(const char *func)
{
if (k_mutex_unlock(&print_mutex) != 0) {
LOG_ERR("Fatal error in mutex_unlock in %s\n", func);
k_fatal_halt(K_ERR_KERNEL_PANIC);
}
}
#define print_mutex_unlock() print_mutex_unlock_impl(__func__)
struct dac_info {
float lo;
float hi;
unsigned num;
};
#ifdef PRINT_DAC
#define MAX_DAC (1 << 20) - 1
static void
print_dac(const struct dac_info *info, uint32_t val)
{
k_mutex_lock(&print_mutex, K_FOREVER);
float volt = (info->hi - info->lo) * val / MAX_DAC
+ info->lo;
LOG_PRINTK("DAC\t%u\t%f\n", info->num, volt);
print_mutex_unlock();
}
#endif
static void
dac_thread(void *p1, void *p2, void *p3)
{
ARG_UNUSED(p2);
ARG_UNUSED(p3);
const struct dac_info *info = p1;
uint32_t val = (1 << 19);
int incr = 1;
#ifdef PRINT_DAC
int print_cntr = 0;
#endif
for (;;) {
dac_write_v(info->num, val);
if (val == 0xFFFFF) {
incr = -1;
} else if (val == 0) {
incr = 1;
}
val += incr;
#ifdef PRINT_DAC
if (print_cntr == 8000) {
print_cntr = 0;
print_dac(info);
}
#endif
k_sleep(K_NSEC(125));
}
}
struct adc_info {
float hi;
unsigned num;
unsigned wid;
};
static void
print_adc(const struct adc_info *info, int32_t val)
{
k_mutex_lock(&print_mutex, K_FOREVER);
const uint32_t bitnum = (1 << info->wid) - 1;
float volt = info->hi / bitnum * val;
LOG_PRINTK("ADC\t%u\t%f\n", info->num, volt);
print_mutex_unlock();
}
static void
adc_thread(void *p1, void *p2, void *p3)
{
ARG_UNUSED(p2);
ARG_UNUSED(p3);
const struct adc_info *info = p1;
int32_t v;
for (;;) {
v = adc_read(info->num, info->wid);
print_adc(info, v);
k_sleep(K_MSEC(1000));
}
}
#define MK_DAC_INFO(n, lo, hi) [n] = {lo, hi, n}
const struct dac_info dac_info[DAC_MAX] = {
MK_DAC_INFO(0, -10, 10),
MK_DAC_INFO(1, -10, 10),
MK_DAC_INFO(2, -10, 10),
MK_DAC_INFO(3, -10, 10),
MK_DAC_INFO(4, -10, 10),
MK_DAC_INFO(5, -10, 10),
MK_DAC_INFO(6, -10, 10),
MK_DAC_INFO(7, -10, 10)
};
#undef MK_DAC_INFO
#define STACKSIZ 2048
#define MKSTACK(name, num) \
K_THREAD_STACK_DEFINE(name##_stk_##num, STACKSIZ)
#define DAC_STACK(n) MKSTACK(dac, n)
DAC_STACK(0);
DAC_STACK(1);
DAC_STACK(2);
DAC_STACK(3);
DAC_STACK(4);
DAC_STACK(5);
DAC_STACK(6);
DAC_STACK(7);
#undef DAC_STACK
const struct adc_info adc_info[ADC_MAX] = {
// TODO
};
#define ADC_STACK(n) MKSTACK(adc, n)
ADC_STACK(0);
ADC_STACK(1);
ADC_STACK(2);
ADC_STACK(3);
ADC_STACK(4);
ADC_STACK(5);
ADC_STACK(6);
ADC_STACK(7);
#undef ADC_STACK
#undef MKSTACK
void
main(void)
{
struct k_thread dac_tids[8];
struct k_thread adc_tids[8];
LOG_PRINTK("DAC ADC test program.\n");
init_dacs();
#define CREATE_THREAD(name, num) \
k_thread_create(&name##_tids[num], \
(k_thread_stack_t *) name##_stk_##num, \
K_THREAD_STACK_SIZEOF(&name##_stk_##num), \
name##_thread, &name##_info[num], NULL, NULL, \
-1, K_FP_REGS, K_MSEC(10))
CREATE_THREAD(dac, 0);
CREATE_THREAD(dac, 1);
CREATE_THREAD(dac, 2);
CREATE_THREAD(dac, 3);
CREATE_THREAD(dac, 4);
CREATE_THREAD(dac, 5);
CREATE_THREAD(dac, 6);
CREATE_THREAD(dac, 7);
CREATE_THREAD(adc, 0);
CREATE_THREAD(adc, 1);
CREATE_THREAD(adc, 2);
CREATE_THREAD(adc, 3);
CREATE_THREAD(adc, 4);
CREATE_THREAD(adc, 5);
CREATE_THREAD(adc, 6);
CREATE_THREAD(adc, 7);
#undef CREATE_THREAD
}

View File

@ -1,120 +0,0 @@
#include <errno.h>
#include <zephyr/net/socket.h>
#include <zephyr/zephyr.h>
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(test_ethernet);
#define PORT 6626
static int
ip_init(void)
{
int sock;
sock = zsock_socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sock < 0) {
LOG_ERR("error: socket: %d", sock);
k_fatal_halt(K_ERR_KERNEL_PANIC);
}
struct sockaddr_in addr = {
.sin_family = AF_INET,
.sin_addr = {.s_addr = htonl(INADDR_ANY)},
.sin_port = htons(PORT)
};
if (zsock_bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
LOG_ERR("error: bind: %d", errno);
k_fatal_halt(K_ERR_KERNEL_PANIC);
}
if (zsock_listen(sock, 2) < 0) {
LOG_ERR("error: listen: %d", errno);
k_fatal_halt(K_ERR_KERNEL_PANIC);
}
return sock;
}
static int
get_client(int server)
{
int client;
struct sockaddr_in addr;
socklen_t len = sizeof(addr);
do {
client = zsock_accept(server, (struct sockaddr *)&addr, &len);
if (client < 0)
LOG_WRN("error in accept: %d", errno);
} while (client < 0);
char ipaddr[32];
zsock_inet_ntop(addr.sin_family, &addr.sin_addr, ipaddr, sizeof(ipaddr));
LOG_PRINTK("Connection: %s\n", ipaddr);
return client;
}
static int
send_all(int sock, char *buf, int len)
{
do {
int sent = zsock_send(sock, buf, len, 0);
if (sent < 0) {
LOG_WRN("error in send: %d", errno);
return 0;
}
buf += sent;
len -= sent;
} while (len > 0);
return 1;
}
static void
print_buf_escaped(const char *buf, size_t len)
{
for (size_t i = 0; i < len; i++) {
if (*buf < 0x20 || *buf >= 0x7F)
LOG_PRINTK("[%02x]", *buf++);
else
LOG_PRINTK("%c", *buf++);
}
}
static void
client_comm(int sock)
{
for (;;) {
char buf[256];
ssize_t len = zsock_recv(sock, buf, sizeof(buf), 0);
if (len < 0) {
LOG_WRN("Error in client socket: %d", errno);
return;
} else if (len == 0) {
LOG_INF("Client disconnected");
return;
}
print_buf_escaped(buf, len);
if (!send_all(sock, buf, len))
return;
}
}
/* DHCP is done before main(), so no manual DHCP setup required. */
void
main(void)
{
LOG_PRINTK("Init test server...\n");
int server_sock = ip_init();
LOG_PRINTK("Test server waiting on %d\n", PORT);
for (;;) {
int client_sock = get_client(server_sock);
client_comm(client_sock);
zsock_close(client_sock);
}
}

View File

@ -1,3 +0,0 @@
#pragma once
#define get_thread_name() k_thread_name_get(k_current_get())