From dc14a7cb1c6e0a9dc4d46b65036c457f599b4dbc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81d=C3=A1m=20Kov=C3=A1cs?= Date: Thu, 27 Mar 2025 16:10:02 +0100 Subject: [PATCH] feat: base project --- CMakeLists.txt | 25 ++++++++++++ build.zig | 57 +++++++++++++++++++++++++++ build.zig.zon | 52 +++++++++++++++++++++++++ config/lwipopts.h | 89 +++++++++++++++++++++++++++++++++++++++++++ config/pico/version.h | 22 +++++++++++ src/main.zig | 47 +++++++++++++++++++++++ 6 files changed, 292 insertions(+) create mode 100644 CMakeLists.txt create mode 100644 build.zig create mode 100644 build.zig.zon create mode 100644 config/lwipopts.h create mode 100644 config/pico/version.h create mode 100644 src/main.zig diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..584a273 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,25 @@ +cmake_minimum_required(VERSION 3.13) + +# Initialize the Pico SDK +include(${PICO_SDK_PATH}/external/pico_sdk_import.cmake) +include_directories(${CMAKE_SOURCE_DIR}/config) +project(${PROJ_NAME}) +pico_sdk_init() +add_executable(${PROJ_NAME}) + +if (STDIO_USB) + pico_enable_stdio_uart(${PROJ_NAME} 0) + pico_enable_stdio_usb(${PROJ_NAME} 1) +endif() + +if (STDIO_UART) + pico_enable_stdio_uart(${PROJ_NAME} 1) + pico_enable_stdio_usb(${PROJ_NAME} 0) +endif() + +# Adjust libraries as needed +target_link_libraries(${PROJ_NAME} ${APP_PICO_LIBS} ${CMAKE_SOURCE_DIR}/zig-out/${PROJ_NAME}.a) + +# Generate binary +pico_add_extra_outputs(${PROJ_NAME}) + diff --git a/build.zig b/build.zig new file mode 100644 index 0000000..6dc6053 --- /dev/null +++ b/build.zig @@ -0,0 +1,57 @@ +const std = @import("std"); +const pico = @import("pico_sdk").pico_sdk; + +// Modify proj_name for your project name +const proj_name = "pico_doorbell"; + +// supported board: pico, pico_w, pico2, pico2_w +// Modify board_name for your board +const board_name = "pico_w"; +// supported pico platform: rp2040, rp2350-arm-s, rp2350-riscv +// Modify pico_platform for select arm or risc-v, but the risc-v is not supported. +const pico_platform = "rp2040"; + +pub fn build(b: *std.Build) anyerror!void { + const stdio_type = .usb; + const cwy43_arch = .threadsafe_background; + const board = try pico.getBoardConfig(board_name, pico_platform, stdio_type, cwy43_arch); + + const target = try pico.getCrossTarget(pico_platform); + const optimize = b.standardOptimizeOption(.{}); + + const lib = b.addStaticLibrary(.{ + .name = "zig-pico", + .root_source_file = b.path("src/main.zig"), + .target = std.Build.resolveTargetQuery(b, target), + .optimize = optimize, + }); + + const option: pico.PicoAppOption = .{ + .app_name = comptime proj_name, + .app_lib = lib, + .board = board, + // additional pico libs for application, it is none in blink application + .pico_libs = "pico_cyw43_arch_lwip_threadsafe_background", + }; + + std.log.info("Begin build app\n", .{}); + + const pico_build = try pico.addPicoApp(b, option); + + const uf2_create_step = b.addInstallFile(b.path("build/pico_doorbell.uf2"), "pico_doorbell.uf2"); + uf2_create_step.step.dependOn(pico_build); + + const uf2_step = b.step("uf2", "Create firmware.uf2"); + uf2_step.dependOn(&uf2_create_step.step); + + const elf_create_step = b.addInstallFile(b.path("build/pico_doorbell.elf"), "pico_doorbell.elf"); + elf_create_step.step.dependOn(pico_build); + + const elf_step = b.step("elf", "Create firmware.elf"); + elf_step.dependOn(&elf_create_step.step); + + const copy_step = b.step("copy", "Copy firmware"); + copy_step.dependOn(uf2_step); + copy_step.dependOn(elf_step); + b.default_step = copy_step; +} diff --git a/build.zig.zon b/build.zig.zon new file mode 100644 index 0000000..ebc082a --- /dev/null +++ b/build.zig.zon @@ -0,0 +1,52 @@ +.{ + // This is the default name used by packages depending on this one. For + // example, when a user runs `zig fetch --save `, this field is used + // as the key in the `dependencies` table. Although the user can choose a + // different name, most users will stick with this provided value. + // + // It is redundant to include "zig" in this name because it is already + // within the Zig package namespace. + .name = .zig_pico_doorbell2, + + // This is a [Semantic Version](https://semver.org/). + // In a future version of Zig it will be used for package deduplication. + .version = "0.0.0", + + // Together with name, this represents a globally unique package + // identifier. This field is generated by the Zig toolchain when the + // package is first created, and then *never changes*. This allows + // unambiguous detection of one package being an updated version of + // another. + // + // When forking a Zig project, this id should be regenerated (delete the + // field and run `zig build`) if the upstream project is still maintained. + // Otherwise, the fork is *hostile*, attempting to take control over the + // original project's identity. Thus it is recommended to leave the comment + // on the following line intact, so that it shows up in code reviews that + // modify the field. + .fingerprint = 0x9bf2eb3e009a59d0, // Changing this has security and trust implications. + + // Tracks the earliest Zig version that the package considers to be a + // supported use case. + .minimum_zig_version = "0.14.0", + + // This field is optional. + // Each dependency must either provide a `url` and `hash`, or a `path`. + // `zig build --fetch` can be used to fetch all dependencies of a package, recursively. + // Once all dependencies are fetched, `zig build` no longer requires + // internet connectivity. + .dependencies = .{ + .pico_sdk = .{ + .url = "git+https://github.com/adix7/zig-pico-cmake.git#8adc8a40000174065c2525531de4f46800233a07", + .hash = "pico_sdk-0.2.0-0FI1kYdcAAD3yWZDXMQdsiYBbTvlUku-AHXIX8DI50k6", + }, + }, + .paths = .{ + "build.zig", + "build.zig.zon", + "src", + // For example... + //"LICENSE", + //"README.md", + }, +} diff --git a/config/lwipopts.h b/config/lwipopts.h new file mode 100644 index 0000000..997ed7b --- /dev/null +++ b/config/lwipopts.h @@ -0,0 +1,89 @@ +#ifndef __LWIPOPTS_H__ +#define __LWIPOPTS_H__ + +// Common settings used in most of the pico_w examples +// (see https://www.nongnu.org/lwip/2_1_x/group__lwip__opts.html for details) + +// allow override in some examples +#ifndef NO_SYS +#define NO_SYS 1 +#endif +// allow override in some examples +#ifndef LWIP_SOCKET +#define LWIP_SOCKET 0 +#endif +#if PICO_CYW43_ARCH_POLL +#define MEM_LIBC_MALLOC 1 +#else +// MEM_LIBC_MALLOC is incompatible with non polling versions +#define MEM_LIBC_MALLOC 0 +#endif +#define MEM_ALIGNMENT 4 +#define MEM_SIZE 4000 +#define MEMP_NUM_TCP_SEG 32 +#define MEMP_NUM_ARP_QUEUE 10 +#define PBUF_POOL_SIZE 24 +#define LWIP_ARP 1 +#define LWIP_ETHERNET 1 +#define LWIP_ICMP 1 +#define LWIP_RAW 1 +#define TCP_WND (8 * TCP_MSS) +#define TCP_MSS 1460 +#define TCP_SND_BUF (8 * TCP_MSS) +#define TCP_SND_QUEUELEN ((4 * (TCP_SND_BUF) + (TCP_MSS - 1)) / (TCP_MSS)) +#define LWIP_NETIF_STATUS_CALLBACK 1 +#define LWIP_NETIF_LINK_CALLBACK 1 +#define LWIP_NETIF_HOSTNAME 1 +#define LWIP_NETCONN 0 +#define MEM_STATS 0 +#define SYS_STATS 0 +#define MEMP_STATS 0 +#define LINK_STATS 0 +// #define ETH_PAD_SIZE 2 +#define LWIP_CHKSUM_ALGORITHM 3 +#define LWIP_DHCP 1 +#define LWIP_IPV4 1 +#define LWIP_TCP 1 +#define LWIP_UDP 1 +#define LWIP_DNS 1 +#define LWIP_TCP_KEEPALIVE 1 +#define LWIP_NETIF_TX_SINGLE_PBUF 1 +#define DHCP_DOES_ARP_CHECK 0 +#define LWIP_DHCP_DOES_ACD_CHECK 0 + +#ifndef NDEBUG +#define LWIP_DEBUG 1 +#define LWIP_STATS 1 +#define LWIP_STATS_DISPLAY 1 +#endif + +#define ETHARP_DEBUG LWIP_DBG_OFF +#define NETIF_DEBUG LWIP_DBG_OFF +#define PBUF_DEBUG LWIP_DBG_OFF +#define API_LIB_DEBUG LWIP_DBG_OFF +#define API_MSG_DEBUG LWIP_DBG_OFF +#define SOCKETS_DEBUG LWIP_DBG_OFF +#define ICMP_DEBUG LWIP_DBG_OFF +#define INET_DEBUG LWIP_DBG_OFF +#define IP_DEBUG LWIP_DBG_OFF +#define IP_REASS_DEBUG LWIP_DBG_OFF +#define RAW_DEBUG LWIP_DBG_OFF +#define MEM_DEBUG LWIP_DBG_OFF +#define MEMP_DEBUG LWIP_DBG_OFF +#define SYS_DEBUG LWIP_DBG_OFF +#define TCP_DEBUG LWIP_DBG_OFF +#define TCP_INPUT_DEBUG LWIP_DBG_OFF +#define TCP_OUTPUT_DEBUG LWIP_DBG_OFF +#define TCP_RTO_DEBUG LWIP_DBG_OFF +#define TCP_CWND_DEBUG LWIP_DBG_OFF +#define TCP_WND_DEBUG LWIP_DBG_OFF +#define TCP_FR_DEBUG LWIP_DBG_OFF +#define TCP_QLEN_DEBUG LWIP_DBG_OFF +#define TCP_RST_DEBUG LWIP_DBG_OFF +#define UDP_DEBUG LWIP_DBG_OFF +#define TCPIP_DEBUG LWIP_DBG_OFF +#define PPP_DEBUG LWIP_DBG_OFF +#define SLIP_DEBUG LWIP_DBG_OFF +#define DHCP_DEBUG LWIP_DBG_OFF + +#endif /* __LWIPOPTS_H__ */ diff --git a/config/pico/version.h b/config/pico/version.h new file mode 100644 index 0000000..098413e --- /dev/null +++ b/config/pico/version.h @@ -0,0 +1,22 @@ +// This file should look something like this: +// version.h seems not strictly necessary + +/* + * Copyright (c) 2020 Raspberry Pi (Trading) Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +// --------------------------------------- +// THIS FILE IS AUTOGENERATED; DO NOT EDIT +// --------------------------------------- + +// #ifndef _PICO_VERSION_H +// #define _PICO_VERSION_H + +// #define PICO_SDK_VERSION_MAJOR 1 +// #define PICO_SDK_VERSION_MINOR 5 +// #define PICO_SDK_VERSION_REVISION 1 +// #define PICO_SDK_VERSION_STRING "1.5.1" + +// #endif diff --git a/src/main.zig b/src/main.zig new file mode 100644 index 0000000..238e574 --- /dev/null +++ b/src/main.zig @@ -0,0 +1,47 @@ +pub const p = @cImport({ + @cInclude("pico.h"); + @cInclude("stdio.h"); + @cInclude("pico/stdlib.h"); + // PICO W specific header + @cInclude("pico/cyw43_arch.h"); +}); +const std = @import("std"); +const BUTTON_PIN = 15; +const GPIO_IN = false; + +// Basically the pico_w blink sample +export fn main() c_int { + _ = p.stdio_init_all(); + if (p.cyw43_arch_init() != 0) { + return -1; + } + + p.cyw43_arch_enable_sta_mode(); + if (p.cyw43_arch_wifi_connect_timeout_ms(@embedFile("wifi.txt"), @embedFile("password.txt"), p.CYW43_AUTH_WPA2_AES_PSK, 10000) == 1) { + p.cyw43_arch_gpio_put(p.CYW43_WL_GPIO_LED_PIN, true); + return -1; + } + + p.cyw43_arch_gpio_put(p.CYW43_WL_GPIO_LED_PIN, true); + p.sleep_ms(200); + p.cyw43_arch_gpio_put(p.CYW43_WL_GPIO_LED_PIN, false); + + p.gpio_init(BUTTON_PIN); + p.gpio_set_dir(BUTTON_PIN, GPIO_IN); + + // while (true) { + // p.cyw43_arch_gpio_put(p.CYW43_WL_GPIO_LED_PIN, true); + // p.sleep_ms(500); + // p.cyw43_arch_gpio_put(p.CYW43_WL_GPIO_LED_PIN, false); + // p.sleep_ms(1000); + // } + // _ = p.printf("Hello world\n"); + + while (true) { + while (p.gpio_get(BUTTON_PIN)) { + p.cyw43_arch_gpio_put(p.CYW43_WL_GPIO_LED_PIN, true); + p.sleep_ms(50); + } + p.cyw43_arch_gpio_put(p.CYW43_WL_GPIO_LED_PIN, false); + } +}