Zig & D examples clean & refactor

dlang: use importC to get NuttX include
zig: leds_zig added
This commit is contained in:
Matheus Catarino 2024-08-23 14:57:27 -03:00 committed by Xiang Xiao
parent c91a1817aa
commit 89dd0c29e2
10 changed files with 455 additions and 96 deletions

View File

@ -26,7 +26,13 @@ MAINSRC = hello_d_main.d
# hello_d built-in application info
DFLAGS += -oq -betterC
# no garbage collection
DFLAGS += -betterC
# better informations
DFLAGS += -vtls -verrors=context
# like #ifdef/#define NuttX_ImportC
# importC: need $(CC) to compile C file and -P-I to import C includes
DFLAGS += -P-I$(TOPDIR)/include --d-version=NuttX_ImportC --gcc=$(CC)
PROGNAME = $(CONFIG_EXAMPLES_HELLO_D_PROGNAME)
PRIORITY = $(CONFIG_EXAMPLES_HELLO_D_PRIORITY)
STACKSIZE = $(CONFIG_EXAMPLES_HELLO_D_STACKSIZE)

View File

@ -26,16 +26,39 @@ module examples.hello_d_main;
// import core.stdc.stdio : printf;
// import core.stdc.stdlib : malloc, free;
///
pragma(printf)
extern (C) int printf(scope const(char)* fmt, scope...) @nogc nothrow @trusted;
///
extern (C) void* malloc(size_t size) @nogc nothrow @trusted;
///
extern (C) void free(void* ptr) @nogc nothrow @trusted;
version (D_BetterC) // no DRT
{
/// if betterC and LDC, disable moduleinfo and typeinfo
version (LDC)
{
pragma(LDC_no_moduleinfo);
pragma(LDC_no_typeinfo);
}
}
/// use --d-version=NuttX_ImportC to define
version (NuttX_ImportC)
{
/// D compiler will not import C++ symbols
/// so we need to import them manually
/// @nogc, @trusted, @safe, nothrow - not allowed
/// https://issues.dlang.org/show_bug.cgi?id=23812
import nuttx_std : malloc, free, printf; // by default: @system (unsafe)
}
else
{
/// Correctly FFI-import C/C++ symbols (@safe compatibility)
///
pragma(printf)
extern (C) int printf(scope const(char)* fmt, scope...) @nogc nothrow @trusted;
///
extern (C) void* malloc(size_t size) @nogc nothrow @trusted;
///
extern (C) void free(scope void* ptr) @nogc nothrow @trusted;
}
//***************************************************************************
// Private module content
// Private module content (default is public)
//***************************************************************************
private:
@ -43,62 +66,76 @@ private:
extern (C++,class)
struct DHelloWorld
{
@nogc nothrow:
@disable this();
@disable this(this);
this(int secret) @safe pure
{
mSecret = secret;
debug printf("Constructor\n");
}
~this() @safe pure
/// use --d-version=NuttX_ImportC to define
version (NuttX_ImportC)
{
debug printf("Destructor\n");
}
bool HelloWorld() @safe
{
debug printf("HelloWorld: mSecret=%d\n", mSecret);
if (mSecret != 42)
this(int secret)
{
printf("DHelloWorld.HelloWorld: CONSTRUCTION FAILED!\n");
return false;
mSecret = secret;
printf("Constructor\n");
}
else
~this()
{
printf("DHelloWorld.HelloWorld: Hello, World!!\n");
return true;
printf("Destructor\n");
}
bool HelloWorld()
{
printf("HelloWorld: mSecret=%d\n", mSecret);
if (mSecret != 42)
{
printf("DHelloWorld.HelloWorld: CONSTRUCTION FAILED!\n");
return false;
}
else
{
printf("DHelloWorld.HelloWorld: Hello, World!!\n");
return true;
}
}
}
else
{
this(int secret) @safe nothrow @nogc
{
mSecret = secret;
printf("Constructor\n");
}
private int mSecret;
~this() @safe nothrow @nogc
{
printf("Destructor\n");
}
bool HelloWorld() @safe nothrow @nogc
{
printf("HelloWorld: mSecret=%d\n", mSecret);
if (mSecret != 42)
{
printf("DHelloWorld.HelloWorld: CONSTRUCTION FAILED!\n");
return false;
}
else
{
printf("DHelloWorld.HelloWorld: Hello, World!!\n");
return true;
}
}
}
private int mSecret = 0;
}
//***************************************************************************
// Private Data
//***************************************************************************
// Define a statically constructed DHellowWorld instance if D static
// initializers are supported by the platform
// --d-version=D_Initialize
version (D_Initialize)
{
static DHelloWorld g_HelloWorld;
}
//***************************************************************************
// Public Functions
//***************************************************************************
/****************************************************************************
* Name: hello_d_main
****************************************************************************/
// betterC need main function no-mangle.
extern (C)
int hello_d_main(int argc, char*[] argv) nothrow @nogc
extern (C) int hello_d_main(int argc, char*[] argv)
{
version (LDC)
{
@ -118,5 +155,6 @@ int hello_d_main(int argc, char*[] argv) nothrow @nogc
printf("hello_d_main: Saying hello from the instance constructed on the stack\n");
HelloWorld.HelloWorld();
return 0;
}

View File

@ -0,0 +1,39 @@
/****************************************************************************
* apps/examples/hello_d/nuttx_std.c
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
/****************************************************************************
* This is imported to d source using importC
* https://dlang.org/spec/importc.html
****************************************************************************/
#include <nuttx/config.h>
#include <stdio.h>
#include <stdlib.h>
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* hello_d_main
****************************************************************************/

View File

@ -25,7 +25,7 @@ include $(APPDIR)/Make.defs
MAINSRC = hello_zig.zig
# Hello, Zig! built-in application info
ZIGFLAGS += -lc -I$(TOPDIR)/include
PROGNAME = $(CONFIG_EXAMPLES_HELLO_ZIG_PROGNAME)
PRIORITY = $(CONFIG_EXAMPLES_HELLO_ZIG_PRIORITY)
STACKSIZE = $(CONFIG_EXAMPLES_HELLO_ZIG_STACKSIZE)

View File

@ -24,17 +24,35 @@
const std = @import("std");
//****************************************************************************
//* Externs
//* C API - need libc linking (freestanding libc is stubs only)
//****************************************************************************
// NuttX namespace
const NuttX = struct {
pub const c = @cImport({
@cInclude("nuttx/config.h");
@cInclude("stdio.h");
});
pub fn print(comptime fmt: [*:0]const u8, args: anytype) void {
_ = printf(std.fmt.comptimePrint(std.mem.span(fmt), args));
}
};
pub extern fn printf(_format: [*:0]const u8) c_int;
// or (optional) const c = std.c; // from std library (non-full libc)
// typedef alias
const printf = NuttX.c.printf;
//****************************************************************************
//* hello_zig_main
//****************************************************************************
pub export fn main(_argc: c_int, _argv: [*]const [*]const u8) u8 {
_ = _argc;
_ = _argv;
_ = printf("Hello, Zig!\n");
comptime {
// rename to hello_zig_main entry point for nuttx
@export(hello_zig, .{
.name = "hello_zig_main",
.linkage = .weak,
});
}
fn hello_zig(_: c_int, _: ?[*]const [*]const u8) callconv(.C) c_int {
NuttX.print("[{s}]: Hello, Zig!\n", .{NuttX.c.CONFIG_ARCH_BOARD});
return 0;
}

View File

@ -1,40 +0,0 @@
//***************************************************************************
// examples/hello_zig/hello_zig_main.zig
//
// Licensed to the Apache Software Foundation (ASF) under one or more
// contributor license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright ownership. The
// ASF licenses this file to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance with the
// License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations
// under the License.
//
//***************************************************************************
//***************************************************************************
// Included Files
//***************************************************************************
const std = @import("std");
//****************************************************************************
//* Externs
//****************************************************************************
pub extern fn printf(_format: [*:0]const u8) c_int;
//****************************************************************************
//* hello_zig_main
//****************************************************************************
pub export fn hello_zig_main(_argc: c_int, _argv: [*]const [*]const u8) c_int {
_ = _argc;
_ = _argv;
_ = printf("Hello, Zig!\n");
return 0;
}

30
examples/leds_zig/Kconfig Normal file
View File

@ -0,0 +1,30 @@
#
# For a description of the syntax of this configuration file,
# see the file kconfig-language.txt in the NuttX tools repository.
#
config EXAMPLES_LEDS_ZIG
tristate "\"LEDs Zig\" example"
default n
depends on USERLED
---help---
Enable the \"LEDs Zig\" example
if EXAMPLES_LEDS_ZIG
config EXAMPLES_LEDS_ZIG_PROGNAME
string "Program name"
default "leds_zig"
---help---
This is the name of the program that will be used when the
program is installed.
config EXAMPLES_LEDS_ZIG_PRIORITY
int "LEDs Zig task priority"
default 100
config EXAMPLES_LEDS_ZIG_STACKSIZE
int "LEDs Zig stack size"
default DEFAULT_TASK_STACKSIZE
endif

View File

@ -0,0 +1,23 @@
############################################################################
# apps/examples/leds_zig/Make.defs
#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership. The
# ASF licenses this file to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance with the
# License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
############################################################################
ifneq ($(CONFIG_EXAMPLES_LEDS_ZIG),)
CONFIGURED_APPS += $(APPDIR)/examples/leds_zig
endif

View File

@ -0,0 +1,34 @@
############################################################################
# apps/examples/leds_zig/Makefile
#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership. The
# ASF licenses this file to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance with the
# License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
############################################################################
include $(APPDIR)/Make.defs
# LEDS in Zig Example
MAINSRC = leds_zig.zig
# LEDS_zig built-in application info
ZIGFLAGS += -O ReleaseSmall -lc -I$(TOPDIR)/include
PROGNAME = $(CONFIG_EXAMPLES_LEDS_ZIG_PROGNAME)
PRIORITY = $(CONFIG_EXAMPLES_LEDS_ZIG_PRIORITY)
STACKSIZE = $(CONFIG_EXAMPLES_LEDS_ZIG_STACKSIZE)
MODULE = $(CONFIG_EXAMPLES_LEDS_ZIG)
include $(APPDIR)/Application.mk

View File

@ -0,0 +1,211 @@
///**************************************************************************
// examples/leds_zig/leds_zig.zig
//
// Licensed to the Apache Software Foundation (ASF) under one or more
// contributor license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright ownership. The
// ASF licenses this file to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance with the
// License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations
// under the License.
//
///**************************************************************************
///**************************************************************************
// Included Files
///**************************************************************************
const std = @import("std");
// C types not working with Zig comptime, need allocation
const Allocator = std.mem.Allocator;
/// NuttX namespace
const NuttX = struct {
// public constant
pub const c = @cImport({
@cInclude("nuttx/config.h");
@cInclude("sys/ioctl.h");
@cInclude("stdbool.h");
@cInclude("stdlib.h");
@cInclude("stdio.h");
@cInclude("fcntl.h");
@cInclude("sched.h");
@cInclude("errno.h");
@cInclude("signal.h");
@cInclude("unistd.h");
@cInclude("nuttx/leds/userled.h");
});
var g_led_daemon_started: bool = false;
pub fn print(allocator: Allocator, comptime fmt: [*:0]const u8, args: anytype) void {
// comptime buffer[count(fmt, args)] or runtime allocation
const output = if (isComptime(args))
std.fmt.comptimePrint(std.mem.span(fmt), args)
else
std.fmt.allocPrintZ(allocator, std.mem.span(fmt), args) catch @panic("Out of Memory!!");
_ = c.printf(output);
}
pub const exit_t = enum(c_int) {
success = c.EXIT_SUCCESS,
failure = c.EXIT_FAILURE,
};
// private function
// check if value is comptime
inline fn isComptime(val: anytype) bool {
return @typeInfo(@TypeOf(.{val})).Struct.fields[0].is_comptime;
}
export fn led_daemon(_: c_int, _: [*c][*c]u8) callconv(.C) c_int {
var supported: NuttX.c.userled_set_t = 0;
var ledset: NuttX.c.userled_set_t = 0;
var incrementing: bool = true;
// SIGTERM handler
const sigaction_t = NuttX.c.struct_sigaction;
var act: sigaction_t = .{
.sa_flags = NuttX.c.SA_SIGINFO,
.sa_u = .{
._sa_sigaction = sigterm_action,
},
};
_ = NuttX.c.sigemptyset(&act.sa_mask);
_ = NuttX.c.sigaddset(&act.sa_mask, NuttX.c.SIGTERM);
const sig = NuttX.c.sigaction(NuttX.c.SIGTERM, &act, null);
if (sig != 0) {
NuttX.print(global_allocator, "Failed to install SIGTERM handler, errno={}\n", .{sig});
return @intFromEnum(NuttX.exit_t.failure);
}
// Indicate that we are running
const mypid = NuttX.c.getpid();
g_led_daemon_started = true;
NuttX.print(global_allocator, "\nled_daemon (pid# {}): Running\n", .{mypid});
// Open the LED driver
NuttX.print(global_allocator, "led_daemon: Opening {s}\n", .{NuttX.c.CONFIG_EXAMPLES_LEDS_DEVPATH});
const fd = NuttX.c.open(NuttX.c.CONFIG_EXAMPLES_LEDS_DEVPATH, NuttX.c.O_WRONLY);
if (fd < 0) {
NuttX.print(global_allocator, "led_daemon: ERROR: Failed to open {s}: {}\n", .{
NuttX.c.CONFIG_EXAMPLES_LEDS_DEVPATH,
fd,
});
g_led_daemon_started = false;
return @intFromEnum(NuttX.exit_t.failure);
}
// Get the set of LEDs supported
var ret = NuttX.c.ioctl(fd, NuttX.c.ULEDIOC_SUPPORTED, &supported);
if (ret < 0) {
NuttX.print(global_allocator, "led_daemon: ERROR: ioctl(ULEDIOC_SUPPORTED) failed: {}\n", .{ret});
_ = NuttX.c.close(fd);
g_led_daemon_started = false;
return @intFromEnum(NuttX.exit_t.failure);
}
NuttX.print(global_allocator, "led_daemon: Supported LEDs {x}\n", .{supported});
supported &= NuttX.c.CONFIG_EXAMPLES_LEDS_LEDSET;
// Main loop
while (g_led_daemon_started) {
var newset: NuttX.c.userled_set_t = 0;
var tmp: NuttX.c.userled_set_t = 0;
if (incrementing) {
tmp = ledset;
while (newset == ledset) {
tmp += 1;
newset = tmp & supported;
}
if (newset == 0) {
incrementing = false;
continue;
}
} else {
if (ledset == 0) {
incrementing = true;
continue;
}
tmp = ledset;
while (newset == ledset) {
tmp -= 1;
newset = tmp & supported;
}
}
ledset = newset;
NuttX.print(global_allocator, "led_daemon: LED set {x}\n", .{ledset});
ret = NuttX.c.ioctl(fd, NuttX.c.ULEDIOC_SETALL, ledset);
if (ret < 0) {
NuttX.print(global_allocator, "led_daemon: ERROR: ioctl(ULEDIOC_SETALL) failed: {}\n", .{ret});
_ = NuttX.c.close(fd);
g_led_daemon_started = false;
return @intFromEnum(NuttX.exit_t.failure);
}
_ = NuttX.c.usleep(500 * 1000);
}
_ = NuttX.c.close(fd);
return @intFromEnum(NuttX.exit_t.success);
}
export fn sigterm_action(signo: c_int, siginfo: [*c]NuttX.c.siginfo_t, arg: ?*anyopaque) void {
if (signo == NuttX.c.SIGTERM) {
NuttX.print(global_allocator, "SIGTERM received\n", .{});
g_led_daemon_started = false;
NuttX.print(global_allocator, "led_daemon: Terminated.\n", .{});
} else {
NuttX.print(global_allocator, "\nsigterm_action: Received signo={} siginfo={*} arg={*}\n", .{
signo,
siginfo,
arg,
});
}
}
};
// Global allocator
var arena = std.heap.ArenaAllocator.init(std.heap.raw_c_allocator);
const global_allocator = arena.allocator();
export fn leds_zig_main(_: c_int, _: [*][*:0]u8) NuttX.exit_t {
defer arena.deinit();
NuttX.print(global_allocator, "leds_main: Starting the led_daemon\n", .{});
if (NuttX.g_led_daemon_started) {
NuttX.print(global_allocator, "leds_main: led_daemon already running\n", .{});
return .success;
}
const ret = NuttX.c.task_create(
"led_daemon",
NuttX.c.CONFIG_EXAMPLES_LEDS_PRIORITY,
NuttX.c.CONFIG_EXAMPLES_LEDS_STACKSIZE,
NuttX.led_daemon,
null,
);
if (ret < 0) {
NuttX.print(global_allocator, "leds_main: ERROR: Failed to start led_daemon: {}\n", .{ret});
return .failure;
}
NuttX.print(global_allocator, "leds_main: led_daemon started\n", .{});
return .success;
}