forked from EmbeddedTeam/app_photomagnetic
feat: Add Kconfig and conditional build for hello world sample
This commit is contained in:
parent
1f2a92ad04
commit
e74fa5c804
@ -3,7 +3,13 @@ cmake_minimum_required(VERSION 3.20.0)
|
||||
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
|
||||
project(app_photomagnetic)
|
||||
|
||||
|
||||
|
||||
target_include_directories(app PRIVATE include)
|
||||
target_sources(app PRIVATE src/main.cpp)
|
||||
|
||||
|
||||
if(CONFIG_SAMPLE_HELLOWORLD)
|
||||
message("CONFIG_SAMPLE_HELLOWORLD is enabled")
|
||||
target_sources(app PRIVATE src/sample_hello_world.cpp)
|
||||
else()
|
||||
target_sources(app PRIVATE src/main.cpp)
|
||||
endif()
|
||||
|
||||
6
Kconfig
Normal file
6
Kconfig
Normal file
@ -0,0 +1,6 @@
|
||||
menu "app thermotherapy"
|
||||
source "Kconfig.zephyr"
|
||||
endmenu
|
||||
|
||||
config SAMPLE_HELLOWORLD
|
||||
bool "Hello World sample"
|
||||
35
include/com.hpp
Normal file
35
include/com.hpp
Normal file
@ -0,0 +1,35 @@
|
||||
#ifndef __THER_COM_HPP__
|
||||
#define __THER_COM_HPP__
|
||||
|
||||
#include <led_strip_indicator/led_strip_indicator.hpp>
|
||||
#include <uart_com/simple_protocal.hpp>
|
||||
#include <zpp/driver.hpp>
|
||||
#include <zpp/error.hpp>
|
||||
namespace ther {
|
||||
|
||||
template <device *kDev> class Com {
|
||||
public:
|
||||
enum Addr : uint8_t { TEMP = 0, GET_ID, RUNNING_STATE };
|
||||
using CbTableValueType =
|
||||
std::pair<const uint8_t, void (*)(uart_com::DataType)>;
|
||||
static auto Init() -> zpp::error {
|
||||
s_proto->SetRxCallbackTable({GET_ID, Cb::GetId},
|
||||
{RUNNING_STATE, Cb::RunningState});
|
||||
return zpp::ok();
|
||||
}
|
||||
|
||||
private:
|
||||
struct Cb {
|
||||
static auto GetId(uart_com::DataType data) -> void {
|
||||
// TODO
|
||||
}
|
||||
static auto RunningState(uart_com::DataType data) -> void {
|
||||
// TODO
|
||||
}
|
||||
};
|
||||
constexpr static uart_com::SimpleProtocal *s_proto =
|
||||
(uart_com::SimpleProtocal *)(kDev);
|
||||
};
|
||||
} // namespace ther
|
||||
|
||||
#endif
|
||||
11
include/heating.hpp
Normal file
11
include/heating.hpp
Normal file
@ -0,0 +1,11 @@
|
||||
#ifndef __THER_HEATING_HPP__
|
||||
#define __THER_HEATING_HPP__
|
||||
#include <zephyr/device.h>
|
||||
|
||||
namespace ther {
|
||||
template <const device *kDev> class HeatingPad {
|
||||
public:
|
||||
};
|
||||
|
||||
} // namespace ther
|
||||
#endif
|
||||
49
include/infrared.hpp
Normal file
49
include/infrared.hpp
Normal file
@ -0,0 +1,49 @@
|
||||
#ifndef __THER_INFRARED_HPP__
|
||||
#define __THER_INFRARED_HPP__
|
||||
#include <zephyr/device.h>
|
||||
#include <zephyr/drivers/sensor.h>
|
||||
#include <zpp/result.hpp>
|
||||
#include <zpp/value.hpp>
|
||||
#include <zpp/work_queue.hpp>
|
||||
namespace ther {
|
||||
|
||||
template <device *kDev> class Infrared {
|
||||
public:
|
||||
static auto Init() -> zpp::error {
|
||||
static sensor_trigger tri{.type = SENSOR_TRIG_DATA_READY,
|
||||
.chan = SENSOR_CHAN_AMBIENT_TEMP};
|
||||
if (auto r = sensor_trigger_set(
|
||||
kDev, &tri,
|
||||
[](const device *dev, const sensor_trigger *trig) {
|
||||
s_is_data_ready = true;
|
||||
});
|
||||
r != 0) {
|
||||
return -ENODEV;
|
||||
};
|
||||
}
|
||||
static auto GetSensorValue()
|
||||
-> zpp::result<zpp::value<zpp::value_type::AMBIENT_TEMP>> {
|
||||
if (!s_is_data_ready) {
|
||||
return zpp::error_code::k_nodata;
|
||||
}
|
||||
|
||||
if (0 != sensor_sample_fetch(kDev)) {
|
||||
return zpp::error_code::k_io;
|
||||
}
|
||||
|
||||
zpp::value<zpp::value_type::AMBIENT_TEMP> val;
|
||||
if (0 != sensor_channel_get(kDev, SENSOR_CHAN_AMBIENT_TEMP, &val)) {
|
||||
return zpp::error_code::k_io;
|
||||
}
|
||||
|
||||
s_is_data_ready = false;
|
||||
return val;
|
||||
}
|
||||
|
||||
private:
|
||||
inline static bool s_is_data_ready{false};
|
||||
};
|
||||
|
||||
} // namespace ther
|
||||
|
||||
#endif
|
||||
45
include/ntc.hpp
Normal file
45
include/ntc.hpp
Normal file
@ -0,0 +1,45 @@
|
||||
#ifndef THER_NTC_HPP
|
||||
#define THER_NTC_HPP
|
||||
#include <zephyr/device.h>
|
||||
#include <zephyr/drivers/sensor.h>
|
||||
#include <zpp/result.hpp>
|
||||
#include <zpp/value.hpp>
|
||||
|
||||
namespace ther {
|
||||
|
||||
template <device *...kNtcDev> class Ntc {
|
||||
public:
|
||||
/// Read all NTC sensors, return the maximum temperature value.
|
||||
/// Returns error if every sensor read fails.
|
||||
static auto GetSensorValue()
|
||||
-> zpp::result<zpp::value<zpp::value_type::AMBIENT_TEMP>> {
|
||||
bool found = false;
|
||||
zpp::value<zpp::value_type::AMBIENT_TEMP> max_val;
|
||||
|
||||
for (const auto *dev : s_devices) {
|
||||
if (0 != sensor_sample_fetch(dev))
|
||||
continue;
|
||||
|
||||
zpp::value<zpp::value_type::AMBIENT_TEMP> val;
|
||||
if (0 != sensor_channel_get(dev, SENSOR_CHAN_AMBIENT_TEMP, &val))
|
||||
continue;
|
||||
|
||||
if (!found || val.to_double() > max_val.to_double()) {
|
||||
max_val = val;
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (found)
|
||||
return max_val;
|
||||
|
||||
return zpp::error_code::k_io;
|
||||
}
|
||||
|
||||
private:
|
||||
static constexpr device *s_devices[] = {kNtcDev...};
|
||||
};
|
||||
|
||||
} // namespace ther
|
||||
|
||||
#endif // THER_NTC_HPP
|
||||
6
prj.conf
6
prj.conf
@ -1,14 +1,14 @@
|
||||
CONFIG_STDOUT_CONSOLE=y
|
||||
CONFIG_CBPRINTF_FP_SUPPORT=y
|
||||
CONFIG_STD_CPP20=y
|
||||
CONFIG_STD_CPP23=y
|
||||
CONFIG_CPP=y
|
||||
CONFIG_REQUIRES_FULL_LIBCPP=y
|
||||
|
||||
CONFIG_CONSOLE=y
|
||||
CONFIG_SERIAL=y
|
||||
CONFIG_UART_INTERRUPT_DRIVEN=y
|
||||
CONFIG_PMC_COM=y
|
||||
CONFIG_HWINFO=y
|
||||
|
||||
CONFIG_ADC=y
|
||||
CONFIG_REBOOT=y
|
||||
CONFIG_WATCHDOG=y
|
||||
CONFIG_WATCHDOG=y
|
||||
|
||||
89
src/main.cpp
89
src/main.cpp
@ -3,47 +3,85 @@
|
||||
#include <zephyr/drivers/hwinfo.h>
|
||||
#include <zephyr/drivers/sensor.h>
|
||||
|
||||
#include <led_strip_indicator/led_strip_indicator.hpp>
|
||||
#include <uart_com/protocal.hpp>
|
||||
#include <zpp/device.hpp>
|
||||
|
||||
#include "watchdog.hpp"
|
||||
#include "zephyr/drivers/gpio.h"
|
||||
#include "zephyr/kernel.h"
|
||||
#include "zpp/fmt.hpp"
|
||||
#include "zpp/timer.hpp"
|
||||
#include <bitset>
|
||||
#include <led_strip_indicator/led_strip_indicator.hpp>
|
||||
#include <uart_com/simple_protocal.hpp>
|
||||
#include <zpp/device.hpp>
|
||||
#include <zpp/value.hpp>
|
||||
namespace {
|
||||
constexpr uart_com::SimpleProtocal::CallbackType kCbTable[] = {};
|
||||
|
||||
auto sensor = DEVICE_DT_GET(DT_NODELABEL(godtek));
|
||||
auto &pmc = ZPP_DRV_GET(uart_com::Protocal, DT_NODELABEL(pm_protocal));
|
||||
auto &pmc =
|
||||
*(uart_com::SimpleProtocal *)(DEVICE_DT_GET(DT_NODELABEL(pm_protocal)));
|
||||
|
||||
auto &led_strip = ZPP_DRV_GET(ledstrip::Indicator, DT_NODELABEL(indicator));
|
||||
enum Command { kTemp = 0x00, kGetId, kRunningState };
|
||||
enum RunningState {};
|
||||
constexpr auto kDeviceIdSize = 20;
|
||||
enum StatusId : uint8_t { kStandby, kRunning, kPause, kError};
|
||||
volatile bool flag{false};
|
||||
enum StatusId : uint8_t { kStandby, kRunning, kPause, kError };
|
||||
gpio_dt_spec led_g = GPIO_DT_SPEC_GET(DT_NODELABEL(led_g), gpios);
|
||||
k_timer led_timer;
|
||||
} // namespace
|
||||
|
||||
auto main(void) -> int {
|
||||
gpio_pin_configure_dt(&led_g, GPIO_OUTPUT_ACTIVE);
|
||||
k_timer_init(&led_timer, [](k_timer* tim) {
|
||||
gpio_pin_toggle_dt(&led_g);
|
||||
}, [](k_timer* tim) {});
|
||||
k_timer_start(&led_timer, K_NO_WAIT, K_SECONDS(1));
|
||||
pmc.SetRxCallback(kGetId, [](uart_com::DataType data) -> void {
|
||||
#define GET_NTC_DRV(node) DEVICE_DT_GET(node),
|
||||
const device *ntc_sensor[] = {
|
||||
DT_FOREACH_CHILD(DT_NODELABEL(mcp3208), GET_NTC_DRV)};
|
||||
|
||||
struct Cb {
|
||||
static auto GetId(uart_com::DataType data) -> void {
|
||||
uint8_t buffer[kDeviceIdSize];
|
||||
auto size = hwinfo_get_device_id(buffer, sizeof(buffer));
|
||||
pmc.Send(kGetId, uart_com::DataType(buffer, size));
|
||||
});
|
||||
|
||||
pmc.SetRxCallback(kRunningState, [](uart_com::DataType data) -> void {
|
||||
}
|
||||
static auto RunningState(uart_com::DataType data) -> void {
|
||||
auto state = static_cast<StatusId>(data[0]);
|
||||
pmc.Send(
|
||||
kRunningState,
|
||||
uart_com::DataType(reinterpret_cast<uint8_t *>(&state), sizeof(state)));
|
||||
led_strip.Status(state).on_error([](zpp::error_code code) {});
|
||||
});
|
||||
}
|
||||
static constexpr std::pair<const uint8_t,
|
||||
uart_com::SimpleProtocal::CallbackType>
|
||||
kCbTable[] = {
|
||||
{kGetId, GetId},
|
||||
{kRunningState, RunningState},
|
||||
};
|
||||
};
|
||||
enum SensorType {
|
||||
NTC0 = 0,
|
||||
NTC1,
|
||||
NTC2,
|
||||
NTC3,
|
||||
INFRARED,
|
||||
};
|
||||
std::bitset<5> bs;
|
||||
auto SensorTriggerCallback(const device *dev, const sensor_trigger *trig)
|
||||
-> void {
|
||||
if (dev == sensor) {
|
||||
bs.set(NTC0);
|
||||
}
|
||||
}
|
||||
auto InitSensors() {
|
||||
static const sensor_trigger tri{.chan = SENSOR_CHAN_AMBIENT_TEMP,
|
||||
.type = SENSOR_TRIG_DATA_READY};
|
||||
sensor_trigger_set(sensor, &tri, SensorTriggerCallback);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
auto main(void) -> int {
|
||||
gpio_pin_configure_dt(&led_g, GPIO_OUTPUT_ACTIVE);
|
||||
k_timer_init(
|
||||
&led_timer, [](k_timer *tim) { gpio_pin_toggle_dt(&led_g); },
|
||||
[](k_timer *tim) {});
|
||||
k_timer_start(&led_timer, K_NO_WAIT, K_SECONDS(1));
|
||||
pmc.SetRxCallbackTable(Cb::kCbTable);
|
||||
|
||||
auto wdt = app::WatchDogConfig{};
|
||||
sensor_trigger tri{.type = SENSOR_TRIG_DATA_READY,
|
||||
.chan = SENSOR_CHAN_AMBIENT_TEMP};
|
||||
@ -61,12 +99,19 @@ auto main(void) -> int {
|
||||
sensor_channel_get(sensor, SENSOR_CHAN_AMBIENT_TEMP, &val);
|
||||
const uint8_t data[2] = {static_cast<uint8_t>(val.val1),
|
||||
static_cast<uint8_t>(val.val2)};
|
||||
pmc.Send("temp", data);
|
||||
pmc.Send(kTemp, data);
|
||||
}
|
||||
for (auto ntc: ntc_sensor) {
|
||||
if (sensor_sample_fetch_chan(ntc, SENSOR_CHAN_AMBIENT_TEMP) == 0) {
|
||||
sensor_channel_get(ntc, SENSOR_CHAN_AMBIENT_TEMP, &val);
|
||||
const uint8_t data[2] = {static_cast<uint8_t>(val.val1),
|
||||
static_cast<uint8_t>(val.val2)};
|
||||
pmc.Send(kTemp, data);
|
||||
}
|
||||
}
|
||||
|
||||
flag = false;
|
||||
}
|
||||
wdt.Feed();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
18
src/sample_hello_world.cpp
Normal file
18
src/sample_hello_world.cpp
Normal file
@ -0,0 +1,18 @@
|
||||
#include <zephyr/drivers/led.h>
|
||||
#include <zephyr/kernel.h>
|
||||
|
||||
led_dt_spec status = LED_DT_SPEC_GET(DT_NODELABEL(status_led));
|
||||
auto main() -> int {
|
||||
printk("hello world %s\n", CONFIG_BOARD);
|
||||
printk("hello world %s\n", CONFIG_BOARD);
|
||||
printk("hello world %s\n", CONFIG_BOARD);
|
||||
printk("hello world %s\n", CONFIG_BOARD);
|
||||
while (true) {
|
||||
printk("hello world\n");
|
||||
led_on_dt(&status);
|
||||
k_sleep(K_MSEC(1000));
|
||||
led_off_dt(&status);
|
||||
k_sleep(K_MSEC(1000));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
1
src/sample_ntc.cpp
Normal file
1
src/sample_ntc.cpp
Normal file
@ -0,0 +1 @@
|
||||
auto main() -> int {}
|
||||
@ -0,0 +1,8 @@
|
||||
common:
|
||||
platform:
|
||||
- native_sim/native/64
|
||||
- nucleo_f429zi
|
||||
tests:
|
||||
sample.helloworld:
|
||||
extra_configs:
|
||||
- CONFIG_SAMPLE_HELLOWORLD=y
|
||||
47
west.yml
Normal file
47
west.yml
Normal file
@ -0,0 +1,47 @@
|
||||
manifest:
|
||||
projects:
|
||||
- import:
|
||||
name-allowlist:
|
||||
- cmsis_6
|
||||
- hal_stm32
|
||||
- hal_ti
|
||||
path-prefix: extern
|
||||
name: zephyr
|
||||
path: zephyr
|
||||
remote: zephyr
|
||||
revision: v4.4.0
|
||||
- name: etl
|
||||
path: modules/etl
|
||||
remote: robotstorm
|
||||
revision: master
|
||||
- name: uart_com
|
||||
path: modules/uart_com
|
||||
remote: robotstorm
|
||||
revision: main
|
||||
- name: zpp
|
||||
path: modules/zpp
|
||||
remote: robotstorm
|
||||
revision: dev
|
||||
- name: dr2501a_g070rb
|
||||
path: boards/dr2501a_g070rb
|
||||
remote: robotstorm
|
||||
revision: main
|
||||
- name: led_strip_indicator
|
||||
path: modules/led_strip_indicator
|
||||
remote: robotstorm
|
||||
revision: main
|
||||
- name: godtek_temp
|
||||
path: modules/godtek_temp
|
||||
remote: robotstorm
|
||||
revision: main
|
||||
- name: heading_pad
|
||||
path: modules/heading_pad
|
||||
revision: main
|
||||
url: undefined
|
||||
remotes:
|
||||
- name: zephyr
|
||||
url-base: https://gitcode.com/gh_mirrors/ze
|
||||
- name: robotstorm
|
||||
url-base: https://git.robotstorm.tech/EmbeddedTeam
|
||||
self:
|
||||
west-commands: scripts/west-commands.yml
|
||||
160
zbuild.py
Executable file
160
zbuild.py
Executable file
@ -0,0 +1,160 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Zephyr build helper for app_i_core_link.
|
||||
|
||||
Usage:
|
||||
python zbuild.py dr2501a_g070rb
|
||||
python zbuild.py dr2501a_g070rb -p auto
|
||||
python zbuild.py -p always (auto-detect board from west.yml)
|
||||
|
||||
Options:
|
||||
board Board name (optional, auto-detected from west.yml if omitted)
|
||||
-p PURSE Pristine option: auto / always / never
|
||||
-t TARGET CMake target to run after build, e.g. test / flash
|
||||
|
||||
Steps:
|
||||
1. west topdir → find Zephyr workspace root
|
||||
2. west config --local manifest.file <this_script_dir>/west.yml
|
||||
3. west build [-p PURSE] -b BOARD [-t TARGET] <this_script_dir>
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
|
||||
def get_script_dir() -> str:
|
||||
"""Absolute path to the directory containing this script."""
|
||||
return os.path.dirname(os.path.abspath(__file__))
|
||||
|
||||
|
||||
def run(cmd: list[str], cwd: str | None = None) -> str:
|
||||
"""Run a command and return stdout. Exit on failure."""
|
||||
proc = subprocess.run(cmd, capture_output=True, text=True, cwd=cwd)
|
||||
if proc.returncode != 0:
|
||||
print(f" ✗ {' '.join(cmd)}", file=sys.stderr)
|
||||
print(f" {proc.stderr.strip()}", file=sys.stderr)
|
||||
sys.exit(proc.returncode)
|
||||
return proc.stdout.strip()
|
||||
|
||||
|
||||
def discover_boards(manifest_path: str) -> list[str]:
|
||||
"""Parse west.yml and return board names whose path starts with 'boards/'."""
|
||||
if not os.path.exists(manifest_path):
|
||||
return []
|
||||
|
||||
with open(manifest_path) as f:
|
||||
content = f.read()
|
||||
|
||||
# Match entries like:
|
||||
# - name: <board_name>
|
||||
# path: boards/<something>
|
||||
boards = re.findall(r"name:\s*(\S+)\s*\n\s+path:\s*boards/\S+", content)
|
||||
return boards
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Zephyr build helper for app_i_core_link"
|
||||
)
|
||||
parser.add_argument(
|
||||
"board",
|
||||
nargs="?",
|
||||
default=None,
|
||||
help="Board name (optional, auto-detected from west.yml if omitted)",
|
||||
)
|
||||
parser.add_argument(
|
||||
"-p",
|
||||
"--pristine",
|
||||
default=None,
|
||||
choices=["auto", "always", "never"],
|
||||
help="Pristine build option",
|
||||
)
|
||||
parser.add_argument(
|
||||
"-t",
|
||||
"--target",
|
||||
default=None,
|
||||
help="CMake target to run after build (e.g. test, flash)",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--update",
|
||||
action="store_true",
|
||||
help="Run west update after setting manifest",
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
# ── 0. Auto-detect board from west.yml when not specified ───
|
||||
if args.board is None:
|
||||
script_dir = get_script_dir()
|
||||
manifest = os.path.join(script_dir, "west.yml")
|
||||
boards = discover_boards(manifest)
|
||||
|
||||
if len(boards) == 0:
|
||||
print(
|
||||
" ✗ No board specified and no board found in west.yml "
|
||||
"(no entry with path: boards/...)",
|
||||
file=sys.stderr,
|
||||
)
|
||||
sys.exit(1)
|
||||
elif len(boards) == 1:
|
||||
args.board = boards[0]
|
||||
print(f" → Auto-detected board: {args.board}")
|
||||
else:
|
||||
print(
|
||||
" ✗ No board specified. Multiple boards found in west.yml:",
|
||||
", ".join(boards),
|
||||
"\n Please specify one explicitly.",
|
||||
file=sys.stderr,
|
||||
)
|
||||
sys.exit(1)
|
||||
|
||||
script_dir = get_script_dir()
|
||||
manifest = os.path.join(script_dir, "west.yml")
|
||||
|
||||
print(f" script dir : {script_dir}")
|
||||
print(f" board : {args.board}")
|
||||
print(f" pristine : {args.pristine or '(none)'}")
|
||||
print(f" target : {args.target or '(none)'}")
|
||||
print(f" update : {'yes' if args.update else 'no'}")
|
||||
|
||||
# ── 1. Find workspace root ───────────────────────────────
|
||||
print("\n [1/3] Finding west workspace root...")
|
||||
topdir = run(["west", "topdir"])
|
||||
print(f" → {topdir}")
|
||||
|
||||
# ── 2. Set local manifest ────────────────────────────────
|
||||
print("\n [2/3] Setting local manifest...")
|
||||
if not os.path.exists(manifest):
|
||||
print(f" ✗ manifest not found: {manifest}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
run(["west", "config", "--local", "manifest.file", manifest], cwd=topdir)
|
||||
print(f" → manifest.file = {manifest}")
|
||||
|
||||
# ── 2.5. Run west update (optional) ───────────────────────
|
||||
if args.update:
|
||||
print("\n [2.5/3] Running west update...")
|
||||
run(["west", "update", "--fetch", "smart"], cwd=topdir)
|
||||
print(" → update done")
|
||||
|
||||
# ── 3. Run west build ─────────────────────────────────────
|
||||
print("\n [3/3] Running west build...")
|
||||
build_cmd = ["west", "build"]
|
||||
if args.pristine:
|
||||
build_cmd += ["-p", args.pristine]
|
||||
build_cmd += ["-b", args.board]
|
||||
if args.target:
|
||||
build_cmd += ["-t", args.target]
|
||||
build_cmd += [script_dir]
|
||||
|
||||
print(f" $ {' '.join(build_cmd)}")
|
||||
proc = subprocess.run(build_cmd, cwd=topdir)
|
||||
if proc.returncode != 0:
|
||||
print(f"\n ✗ Build failed (exit code {proc.returncode})")
|
||||
sys.exit(proc.returncode)
|
||||
print("\n ✓ Build succeeded")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Loading…
x
Reference in New Issue
Block a user