remove zephyr
This commit is contained in:
parent
41d7a88619
commit
de970b5dd6
|
@ -1,4 +0,0 @@
|
|||
[submodule "creole"]
|
||||
path = creole
|
||||
url = https://software.mcgoron.com/peter/creole
|
||||
branch = upsilon
|
1
creole
1
creole
|
@ -1 +0,0 @@
|
|||
Subproject commit 52279a9afc6afb3c589216e3f930e3d8d96dd119
|
|
@ -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)
|
|
@ -1,3 +0,0 @@
|
|||
mainmenu "CryoSNOM 1"
|
||||
|
||||
source "Kconfig.zephyr"
|
|
@ -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
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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"
|
|
@ -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");
|
||||
}
|
|
@ -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);
|
|
@ -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;
|
||||
}
|
|
@ -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, ...);
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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, ...);
|
|
@ -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
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -1,3 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#define get_thread_name() k_thread_name_get(k_current_get())
|
Loading…
Reference in New Issue