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})
|
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
|
||||||
project(app_photomagnetic)
|
project(app_photomagnetic)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
target_include_directories(app PRIVATE include)
|
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_STDOUT_CONSOLE=y
|
||||||
CONFIG_CBPRINTF_FP_SUPPORT=y
|
CONFIG_CBPRINTF_FP_SUPPORT=y
|
||||||
CONFIG_STD_CPP20=y
|
CONFIG_STD_CPP23=y
|
||||||
CONFIG_CPP=y
|
CONFIG_CPP=y
|
||||||
CONFIG_REQUIRES_FULL_LIBCPP=y
|
CONFIG_REQUIRES_FULL_LIBCPP=y
|
||||||
|
|
||||||
CONFIG_CONSOLE=y
|
CONFIG_CONSOLE=y
|
||||||
CONFIG_SERIAL=y
|
CONFIG_SERIAL=y
|
||||||
CONFIG_UART_INTERRUPT_DRIVEN=y
|
CONFIG_UART_INTERRUPT_DRIVEN=y
|
||||||
CONFIG_PMC_COM=y
|
|
||||||
CONFIG_HWINFO=y
|
CONFIG_HWINFO=y
|
||||||
|
|
||||||
|
CONFIG_ADC=y
|
||||||
CONFIG_REBOOT=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/hwinfo.h>
|
||||||
#include <zephyr/drivers/sensor.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 "watchdog.hpp"
|
||||||
#include "zephyr/drivers/gpio.h"
|
#include "zephyr/drivers/gpio.h"
|
||||||
#include "zephyr/kernel.h"
|
#include "zephyr/kernel.h"
|
||||||
#include "zpp/fmt.hpp"
|
#include "zpp/fmt.hpp"
|
||||||
#include "zpp/timer.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 {
|
namespace {
|
||||||
|
constexpr uart_com::SimpleProtocal::CallbackType kCbTable[] = {};
|
||||||
|
|
||||||
auto sensor = DEVICE_DT_GET(DT_NODELABEL(godtek));
|
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));
|
auto &led_strip = ZPP_DRV_GET(ledstrip::Indicator, DT_NODELABEL(indicator));
|
||||||
enum Command { kTemp = 0x00, kGetId, kRunningState };
|
enum Command { kTemp = 0x00, kGetId, kRunningState };
|
||||||
enum RunningState {};
|
enum RunningState {};
|
||||||
constexpr auto kDeviceIdSize = 20;
|
constexpr auto kDeviceIdSize = 20;
|
||||||
enum StatusId : uint8_t { kStandby, kRunning, kPause, kError};
|
enum StatusId : uint8_t { kStandby, kRunning, kPause, kError };
|
||||||
volatile bool flag{false};
|
|
||||||
gpio_dt_spec led_g = GPIO_DT_SPEC_GET(DT_NODELABEL(led_g), gpios);
|
gpio_dt_spec led_g = GPIO_DT_SPEC_GET(DT_NODELABEL(led_g), gpios);
|
||||||
k_timer led_timer;
|
k_timer led_timer;
|
||||||
} // namespace
|
|
||||||
|
|
||||||
auto main(void) -> int {
|
#define GET_NTC_DRV(node) DEVICE_DT_GET(node),
|
||||||
gpio_pin_configure_dt(&led_g, GPIO_OUTPUT_ACTIVE);
|
const device *ntc_sensor[] = {
|
||||||
k_timer_init(&led_timer, [](k_timer* tim) {
|
DT_FOREACH_CHILD(DT_NODELABEL(mcp3208), GET_NTC_DRV)};
|
||||||
gpio_pin_toggle_dt(&led_g);
|
|
||||||
}, [](k_timer* tim) {});
|
struct Cb {
|
||||||
k_timer_start(&led_timer, K_NO_WAIT, K_SECONDS(1));
|
static auto GetId(uart_com::DataType data) -> void {
|
||||||
pmc.SetRxCallback(kGetId, [](uart_com::DataType data) -> void {
|
|
||||||
uint8_t buffer[kDeviceIdSize];
|
uint8_t buffer[kDeviceIdSize];
|
||||||
auto size = hwinfo_get_device_id(buffer, sizeof(buffer));
|
auto size = hwinfo_get_device_id(buffer, sizeof(buffer));
|
||||||
pmc.Send(kGetId, uart_com::DataType(buffer, size));
|
pmc.Send(kGetId, uart_com::DataType(buffer, size));
|
||||||
});
|
}
|
||||||
|
static auto RunningState(uart_com::DataType data) -> void {
|
||||||
pmc.SetRxCallback(kRunningState, [](uart_com::DataType data) -> void {
|
|
||||||
auto state = static_cast<StatusId>(data[0]);
|
auto state = static_cast<StatusId>(data[0]);
|
||||||
pmc.Send(
|
pmc.Send(
|
||||||
kRunningState,
|
kRunningState,
|
||||||
uart_com::DataType(reinterpret_cast<uint8_t *>(&state), sizeof(state)));
|
uart_com::DataType(reinterpret_cast<uint8_t *>(&state), sizeof(state)));
|
||||||
led_strip.Status(state).on_error([](zpp::error_code code) {});
|
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{};
|
auto wdt = app::WatchDogConfig{};
|
||||||
sensor_trigger tri{.type = SENSOR_TRIG_DATA_READY,
|
sensor_trigger tri{.type = SENSOR_TRIG_DATA_READY,
|
||||||
.chan = SENSOR_CHAN_AMBIENT_TEMP};
|
.chan = SENSOR_CHAN_AMBIENT_TEMP};
|
||||||
@ -61,12 +99,19 @@ auto main(void) -> int {
|
|||||||
sensor_channel_get(sensor, SENSOR_CHAN_AMBIENT_TEMP, &val);
|
sensor_channel_get(sensor, SENSOR_CHAN_AMBIENT_TEMP, &val);
|
||||||
const uint8_t data[2] = {static_cast<uint8_t>(val.val1),
|
const uint8_t data[2] = {static_cast<uint8_t>(val.val1),
|
||||||
static_cast<uint8_t>(val.val2)};
|
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;
|
flag = false;
|
||||||
}
|
}
|
||||||
wdt.Feed();
|
wdt.Feed();
|
||||||
}
|
}
|
||||||
return 0;
|
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