diff --git a/.clangd b/.clangd index b03c4bc..0d6381c 100644 --- a/.clangd +++ b/.clangd @@ -8,3 +8,7 @@ CompileFlags: - -ffixed-r2 - -ffixed-r3 - -ffixed-r4 + - -fzero-init-padding-bits + - -fno-malloc-dce + Add: + - -Wno-missing-field-initializers diff --git a/CMakeLists.txt b/CMakeLists.txt index 230f163..3c1e8dd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,19 +1,36 @@ -cmake_minimum_required(VERSION 3.24) +cmake_minimum_required(VERSION 3.30) -project(avclan-mockingboard VERSION 1.1 LANGUAGES C CXX) +if(AVCLAN_TARGET_SDK_FILE) +include(${AVCLAN_TARGET_SDK_FILE}) +endif() + +project(avclan-mockingboard VERSION 1.2 LANGUAGES C CXX ASM) + +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) +set(BUILD_TESTING OFF CACHE BOOL "" FORCE) + +# Hardware target (port) selection. The chosen target// directory supplies +# the port implementation sources, the per-target include path, and all +# hardware-specific build configuration (compile defs/options, device-pack +# handling, flashing) via its own CMakeLists, pulled in with add_subdirectory +# below. The matching cross-compiler is selected separately by a toolchain file +# (e.g. cmake/avr-gcc-toolchain.cmake) named in a CMake preset. Adding a new +# board = a sibling target/ directory + a toolchain file + a preset wiring them. +set(AVCLAN_TARGET avr-attiny3216 CACHE STRING "Hardware target (port) to build") +set_property(CACHE AVCLAN_TARGET PROPERTY STRINGS "avr-attiny3216" "pico2" "esp32") + +# --- Firmware configuration options ---------------------------------------- +set(AVCLAN_MSG_QUEUE_SIZE 16 CACHE STRING "Size of incoming/outgoing queues") +set(AVCLAN_FRAME_POOL_N 14 CACHE STRING "Pool allocator capacity for avclan::Frame (must be <= incoming/outgoing queue size)") set(CMAKE_C_STANDARD 23) set(CMAKE_CXX_STANDARD 23) set(CMAKE_C_STANDARD_REQUIRED ON) set(CMAKE_CXX_STANDARD_REQUIRED ON) -set(CMAKE_EXPORT_COMPILE_COMMANDS ON) -set(BUILD_TESTING OFF CACHE BOOL "" FORCE) add_compile_options( -Wall -Wswitch-enum -Werror - $<$:-fno-threadsafe-statics> - $<$:-fno-exceptions> - $<$:-fno-rtti> + # Debug must not be -O0: both the vendored usart.h and avr-libc's # #warning when __OPTIMIZE__ is undefined, and -Werror makes # that fatal. @@ -52,15 +69,6 @@ if(INSTALL_GIT_HOOKS AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/.git") endif() endif() -# Hardware target (port) selection. The chosen target// directory supplies -# the port implementation sources, the per-target include path, and all -# hardware-specific build configuration (compile defs/options, device-pack -# handling, flashing) via its own CMakeLists, pulled in with add_subdirectory -# below. The matching cross-compiler is selected separately by a toolchain file -# (e.g. cmake/avr-gcc-toolchain.cmake) named in a CMake preset. Adding a new -# board = a sibling target/ directory + a toolchain file + a preset wiring them. -set(AVCLAN_TARGET avr-attiny3216 CACHE STRING "Hardware target (port) to build") - # The AVC-LAN stack as a static library: the target-agnostic generic core (no # , no register access). The selected target's port sources and flags # are contributed by its subdirectory. @@ -103,7 +111,7 @@ add_subdirectory(src/avclan/target/${AVCLAN_TARGET}) # --- Polyfill headers for std facilities the toolchain may lack ------------- # tl::expected / tl::optional back-fill std::expected / std::optional (with # C++23 monadic ops) when the build's stdlib predates them. Runs after the port -# subdirectory to provide a port-supplied freestanding stdlib via +# subdirectory to provide a port-supplied freestanding stdlib via # CMAKE_REQUIRED_INCLUDES, if necessary. include(CheckCXXSourceCompiles) include(FetchContent) diff --git a/CMakePresets.json b/CMakePresets.json index 5d61e71..98e206c 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -1,6 +1,24 @@ { - "version": 3, + "version": 9, "configurePresets": [ + { + "name": "debug-base", + "hidden": true, + "description": "Debug build settings", + "generator": "Ninja", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Debug" + } + }, + { + "name": "relwithdebinfo-base", + "hidden": true, + "description": "RelWithDebInfo build settings", + "inherits": "debug-base", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "RelWithDebInfo" + } + }, { "name": "usb0", "hidden": true, @@ -31,20 +49,40 @@ } }, { - "name": "debug-base", + "name": "pico2", "hidden": true, - "description": "Debug build settings", + "binaryDir": "${sourceDir}/out/build/pico2", + "inherits": "debug-base", "cacheVariables": { - "CMAKE_BUILD_TYPE": "Debug" + "AVCLAN_TARGET": "pico2", + "AVCLAN_FRAME_POOL_N": "14", + "AVCLAN_TARGET_SDK_FILE": "${sourceDir}/cmake/pico_sdk_import.cmake", + "PICO_SDK_FETCH_FROM_GIT": true + }, + "environment": { + "PICO_PLATFORM": "rp2350-arm-s", + "PICO_BOARD": "pico2" } }, { - "name": "relwithdebinfo-base", - "hidden": true, - "description": "RelWithDebInfo build settings", - "inherits": "debug-base", - "cacheVariables": { - "CMAKE_BUILD_TYPE": "RelWithDebInfo" + "name": "pico2-gcc", + "displayName": "Pico 2W (GCC)", + "inherits": "pico2", + "description": "", + "generator": "Ninja", + "environment": { + "PICO_COMPILER": "pico_arm_gcc", + "CC": "/usr/bin/gcc-15", + "CXX": "/usr/bin/g++-15" + } + }, + { + "name": "pico2-clang", + "displayName": "Pico 2W (Clang)", + "inherits": "pico2", + "description": "", + "environment": { + "PICO_COMPILER": "pico_arm_clang" } }, { diff --git a/cmake/pico_sdk_import.cmake b/cmake/pico_sdk_import.cmake new file mode 100644 index 0000000..d493cc2 --- /dev/null +++ b/cmake/pico_sdk_import.cmake @@ -0,0 +1,121 @@ +# This is a copy of /external/pico_sdk_import.cmake + +# This can be dropped into an external project to help locate this SDK +# It should be include()ed prior to project() + +# Copyright 2020 (c) 2020 Raspberry Pi (Trading) Ltd. +# +# Redistribution and use in source and binary forms, with or without modification, are permitted provided that the +# following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following +# disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following +# disclaimer in the documentation and/or other materials provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +if (DEFINED ENV{PICO_SDK_PATH} AND (NOT PICO_SDK_PATH)) + set(PICO_SDK_PATH $ENV{PICO_SDK_PATH}) + message("Using PICO_SDK_PATH from environment ('${PICO_SDK_PATH}')") +endif () + +if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT} AND (NOT PICO_SDK_FETCH_FROM_GIT)) + set(PICO_SDK_FETCH_FROM_GIT $ENV{PICO_SDK_FETCH_FROM_GIT}) + message("Using PICO_SDK_FETCH_FROM_GIT from environment ('${PICO_SDK_FETCH_FROM_GIT}')") +endif () + +if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT_PATH} AND (NOT PICO_SDK_FETCH_FROM_GIT_PATH)) + set(PICO_SDK_FETCH_FROM_GIT_PATH $ENV{PICO_SDK_FETCH_FROM_GIT_PATH}) + message("Using PICO_SDK_FETCH_FROM_GIT_PATH from environment ('${PICO_SDK_FETCH_FROM_GIT_PATH}')") +endif () + +if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT_TAG} AND (NOT PICO_SDK_FETCH_FROM_GIT_TAG)) + set(PICO_SDK_FETCH_FROM_GIT_TAG $ENV{PICO_SDK_FETCH_FROM_GIT_TAG}) + message("Using PICO_SDK_FETCH_FROM_GIT_TAG from environment ('${PICO_SDK_FETCH_FROM_GIT_TAG}')") +endif () + +if (PICO_SDK_FETCH_FROM_GIT AND NOT PICO_SDK_FETCH_FROM_GIT_TAG) + set(PICO_SDK_FETCH_FROM_GIT_TAG "master") + message("Using master as default value for PICO_SDK_FETCH_FROM_GIT_TAG") +endif() + +set(PICO_SDK_PATH "${PICO_SDK_PATH}" CACHE PATH "Path to the Raspberry Pi Pico SDK") +set(PICO_SDK_FETCH_FROM_GIT "${PICO_SDK_FETCH_FROM_GIT}" CACHE BOOL "Set to ON to fetch copy of SDK from git if not otherwise locatable") +set(PICO_SDK_FETCH_FROM_GIT_PATH "${PICO_SDK_FETCH_FROM_GIT_PATH}" CACHE FILEPATH "location to download SDK") +set(PICO_SDK_FETCH_FROM_GIT_TAG "${PICO_SDK_FETCH_FROM_GIT_TAG}" CACHE FILEPATH "release tag for SDK") + +if (NOT PICO_SDK_PATH) + if (PICO_SDK_FETCH_FROM_GIT) + include(FetchContent) + set(FETCHCONTENT_BASE_DIR_SAVE ${FETCHCONTENT_BASE_DIR}) + if (PICO_SDK_FETCH_FROM_GIT_PATH) + get_filename_component(FETCHCONTENT_BASE_DIR "${PICO_SDK_FETCH_FROM_GIT_PATH}" REALPATH BASE_DIR "${CMAKE_SOURCE_DIR}") + endif () + FetchContent_Declare( + pico_sdk + GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk + GIT_TAG ${PICO_SDK_FETCH_FROM_GIT_TAG} + ) + + if (NOT pico_sdk) + message("Downloading Raspberry Pi Pico SDK") + # GIT_SUBMODULES_RECURSE was added in 3.17 + if (${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.17.0") + FetchContent_Populate( + pico_sdk + QUIET + GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk + GIT_TAG ${PICO_SDK_FETCH_FROM_GIT_TAG} + GIT_SUBMODULES_RECURSE FALSE + + SOURCE_DIR ${FETCHCONTENT_BASE_DIR}/pico_sdk-src + BINARY_DIR ${FETCHCONTENT_BASE_DIR}/pico_sdk-build + SUBBUILD_DIR ${FETCHCONTENT_BASE_DIR}/pico_sdk-subbuild + ) + else () + FetchContent_Populate( + pico_sdk + QUIET + GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk + GIT_TAG ${PICO_SDK_FETCH_FROM_GIT_TAG} + + SOURCE_DIR ${FETCHCONTENT_BASE_DIR}/pico_sdk-src + BINARY_DIR ${FETCHCONTENT_BASE_DIR}/pico_sdk-build + SUBBUILD_DIR ${FETCHCONTENT_BASE_DIR}/pico_sdk-subbuild + ) + endif () + + set(PICO_SDK_PATH ${pico_sdk_SOURCE_DIR}) + endif () + set(FETCHCONTENT_BASE_DIR ${FETCHCONTENT_BASE_DIR_SAVE}) + else () + message(FATAL_ERROR + "SDK location was not specified. Please set PICO_SDK_PATH or set PICO_SDK_FETCH_FROM_GIT to on to fetch from git." + ) + endif () +endif () + +get_filename_component(PICO_SDK_PATH "${PICO_SDK_PATH}" REALPATH BASE_DIR "${CMAKE_BINARY_DIR}") +if (NOT EXISTS ${PICO_SDK_PATH}) + message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' not found") +endif () + +set(PICO_SDK_INIT_CMAKE_FILE ${PICO_SDK_PATH}/pico_sdk_init.cmake) +if (NOT EXISTS ${PICO_SDK_INIT_CMAKE_FILE}) + message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' does not appear to contain the Raspberry Pi Pico SDK") +endif () + +set(PICO_SDK_PATH ${PICO_SDK_PATH} CACHE PATH "Path to the Raspberry Pi Pico SDK" FORCE) + +include(${PICO_SDK_INIT_CMAKE_FILE}) diff --git a/src/avclan/target/avr-attiny3216/CMakeLists.txt b/src/avclan/target/avr-attiny3216/CMakeLists.txt index 6634849..6ec7870 100644 --- a/src/avclan/target/avr-attiny3216/CMakeLists.txt +++ b/src/avclan/target/avr-attiny3216/CMakeLists.txt @@ -12,6 +12,11 @@ target_sources(avclan PRIVATE ) target_include_directories(avclan PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) +target_compile_options(avclan PUBLIC + $<$:-fno-threadsafe-statics> + $<$:-fno-exceptions> + $<$:-fno-rtti> +) find_program(AVRDUDE avrdude) set(AVR_PROGRAMMER serialupdi CACHE STRING "avrdude programmer hardware") @@ -76,9 +81,6 @@ set_property(CACHE USART_RXMODE PROPERTY STRINGS # tick. 1000 = no correction; set per-board in CMakeUserPresets.json. set(RTC_STATUS_PERIOD_MS 1000 CACHE STRING "Measured ms per nominal RTC status period (1000 = no correction)") -# --- Firmware configuration options ---------------------------------------- -set(AVCLAN_FRAME_POOL_N 14 CACHE STRING "Pool allocator capacity for avclan::Frame (must be <= incoming/outgoing queue size)") - try_compile(LIBC_VERSION_TEST SOURCES "${CMAKE_SOURCE_DIR}/cmake/libc-version-test.cpp" COMPILE_DEFINITIONS -mmcu=${AVR_MCU} diff --git a/src/avclan/target/pico2/CMakeLists.txt b/src/avclan/target/pico2/CMakeLists.txt new file mode 100644 index 0000000..e69de29 diff --git a/src/sniffer.cc b/src/sniffer.cc index a1a2aca..cf5fbfb 100644 --- a/src/sniffer.cc +++ b/src/sniffer.cc @@ -20,7 +20,7 @@ const char *const offon[] = {"OFF", "ON"}; -constexpr uint8_t CACHE_SIZE = 16; +constexpr uint8_t CACHE_SIZE = AVCLAN_MSG_QUEUE_SIZE; static_assert(CACHE_SIZE >= AVCLAN_FRAME_POOL_N, "CACHE_SIZE must be >= avclan::Frame allocator pool capacity");