Add Doxygen, clang-format, cppcheck, and Gitea CI
Doxygen: - Doxyfile: minimal config, HTML output to docs/, no LaTeX - @file/@brief on all source files, full @param/@return on public API - docs/ added to .gitignore clang-format (14, Linux brace style, 4-space, column 100): - .clang-format added - Applied to entire codebase; this commit is the canonical baseline - just format rewrites in-place; just format-check is the CI gate cppcheck (--enable=warning,style,performance,portability): - Linker-symbol pointer comparisons in startup.c suppressed with inline cppcheck-suppress (false positives, not real bugs) - just lint runs cppcheck; zero warnings required to pass Dockerfile gains clang-format, cppcheck, doxygen packages so all tools run inside the existing container -- host stays clean. Gitea Actions (.gitea/workflows/ci.yml): - Four parallel jobs: build, format, lint, docs - All jobs use the same Dockerfile-based image - Doxygen job fails on any warning line in output
This commit is contained in:
15
.clang-format
Normal file
15
.clang-format
Normal file
@@ -0,0 +1,15 @@
|
||||
---
|
||||
BasedOnStyle: LLVM
|
||||
IndentWidth: 4
|
||||
TabWidth: 4
|
||||
UseTab: Never
|
||||
ColumnLimit: 100
|
||||
AlignConsecutiveBitFields: true
|
||||
AlignConsecutiveAssignments: false
|
||||
AlignTrailingComments: true
|
||||
AllowShortFunctionsOnASingleLine: None
|
||||
AllowShortIfStatementsOnASingleLine: Never
|
||||
BreakBeforeBraces: Linux
|
||||
SortIncludes: false
|
||||
SpaceAfterCStyleCast: false
|
||||
SpaceBeforeParens: ControlStatements
|
||||
99
.gitea/workflows/ci.yml
Normal file
99
.gitea/workflows/ci.yml
Normal file
@@ -0,0 +1,99 @@
|
||||
name: CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
pull_request:
|
||||
branches: [main]
|
||||
|
||||
env:
|
||||
IMAGE: ptt-builder
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Build firmware
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Build container image
|
||||
run: docker build -t $IMAGE .
|
||||
|
||||
- name: Compile firmware
|
||||
run: |
|
||||
docker run --rm \
|
||||
--user "$(id -u):$(id -g)" \
|
||||
-v "$PWD:/src" \
|
||||
$IMAGE \
|
||||
sh -c "cmake -B /src/build -G Ninja \
|
||||
-DCMAKE_BUILD_TYPE=MinSizeRel /src \
|
||||
&& ninja -C /src/build"
|
||||
|
||||
- name: Print size
|
||||
run: |
|
||||
docker run --rm \
|
||||
-v "$PWD:/src" \
|
||||
$IMAGE \
|
||||
arm-none-eabi-size /src/build/firmware
|
||||
|
||||
format:
|
||||
name: Check formatting
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Build container image
|
||||
run: docker build -t $IMAGE .
|
||||
|
||||
- name: clang-format check
|
||||
run: |
|
||||
docker run --rm \
|
||||
--user "$(id -u):$(id -g)" \
|
||||
-v "$PWD:/src" \
|
||||
$IMAGE \
|
||||
sh -c "find /src/src /src/include -name '*.c' -o -name '*.h' | \
|
||||
xargs clang-format --dry-run --Werror \
|
||||
--style=file:/src/.clang-format"
|
||||
|
||||
lint:
|
||||
name: Static analysis
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Build container image
|
||||
run: docker build -t $IMAGE .
|
||||
|
||||
- name: cppcheck
|
||||
run: |
|
||||
docker run --rm \
|
||||
--user "$(id -u):$(id -g)" \
|
||||
-v "$PWD:/src" \
|
||||
$IMAGE \
|
||||
sh -c "cppcheck --error-exitcode=1 \
|
||||
--enable=warning,style,performance,portability \
|
||||
--suppress=missingInclude \
|
||||
--inline-suppr \
|
||||
--std=c11 \
|
||||
-I /src/include \
|
||||
/src/src/"
|
||||
|
||||
docs:
|
||||
name: Build documentation
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Build container image
|
||||
run: docker build -t $IMAGE .
|
||||
|
||||
- name: Doxygen
|
||||
run: |
|
||||
docker run --rm \
|
||||
--user "$(id -u):$(id -g)" \
|
||||
-v "$PWD:/src" \
|
||||
$IMAGE \
|
||||
sh -c "cd /src && doxygen Doxyfile 2>&1 | tee /tmp/doxy.log && \
|
||||
! grep -q 'warning:' /tmp/doxy.log"
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1 +1,2 @@
|
||||
build/
|
||||
docs/
|
||||
|
||||
@@ -6,6 +6,9 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
libnewlib-arm-none-eabi \
|
||||
cmake \
|
||||
ninja-build \
|
||||
clang-format \
|
||||
cppcheck \
|
||||
doxygen \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
WORKDIR /src
|
||||
|
||||
21
Doxyfile
Normal file
21
Doxyfile
Normal file
@@ -0,0 +1,21 @@
|
||||
PROJECT_NAME = "ptt-fhss"
|
||||
PROJECT_BRIEF = "Bare-metal PTT firmware for nRF52840 with FHSS"
|
||||
PROJECT_NUMBER =
|
||||
OUTPUT_DIRECTORY = docs
|
||||
INPUT = include src
|
||||
FILE_PATTERNS = *.h *.c
|
||||
RECURSIVE = NO
|
||||
EXTRACT_ALL = YES
|
||||
EXTRACT_STATIC = YES
|
||||
QUIET = YES
|
||||
WARNINGS = YES
|
||||
WARN_IF_UNDOCUMENTED = YES
|
||||
WARN_NO_PARAMDOC = YES
|
||||
GENERATE_HTML = YES
|
||||
HTML_OUTPUT = html
|
||||
HTML_TIMESTAMP = NO
|
||||
GENERATE_LATEX = NO
|
||||
HAVE_DOT = NO
|
||||
OPTIMIZE_OUTPUT_FOR_C = YES
|
||||
JAVADOC_AUTOBRIEF = YES
|
||||
PREDEFINED = NRF52840_XXAA
|
||||
@@ -1,6 +1,27 @@
|
||||
/**
|
||||
* @file fhss.h
|
||||
* @brief FHSS channel sequencer based on AES-128-ECB.
|
||||
*
|
||||
* Both link endpoints derive the same hopping sequence independently from a
|
||||
* shared 128-bit key and a monotonically increasing slot counter. No
|
||||
* synchronisation traffic is required as long as both sides start from the
|
||||
* same slot.
|
||||
*/
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
|
||||
/** @brief Reset the slot counter to zero. */
|
||||
void fhss_init(void);
|
||||
uint8_t fhss_next_channel(void); /* next channel from AES-ECB PRNG sequence */
|
||||
void fhss_sync_tick(void); /* call every FHSS_DWELL_MS ms */
|
||||
|
||||
/**
|
||||
* @brief Return the next channel in the hopping sequence.
|
||||
*
|
||||
* Encrypts the current slot counter big-endian with AES-128-ECB, returns
|
||||
* @c block[0] % 40, and advances the slot counter.
|
||||
*
|
||||
* @return Channel index in [0, 39].
|
||||
*/
|
||||
uint8_t fhss_next_channel(void);
|
||||
|
||||
/** @brief Advance the slot counter without transmitting (receiver side). */
|
||||
void fhss_sync_tick(void);
|
||||
|
||||
@@ -1,4 +1,16 @@
|
||||
/**
|
||||
* @file power.h
|
||||
* @brief Power management: DC/DC regulator, GPIOTE wakeup, SYSTEM_ON sleep.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
/** @brief Enable the DC/DC converter and configure GPIOTE wakeup on the PTT button. */
|
||||
void power_init(void);
|
||||
void power_sleep_until_button(void); /* SYSTEM_ON WFI, woken by GPIOTE event */
|
||||
|
||||
/**
|
||||
* @brief Enter SYSTEM_ON low-power sleep and return on the next GPIOTE event.
|
||||
*
|
||||
* Sets TASKS_LOWPWR then executes WFI. The CPU wakes when the GPIOTE
|
||||
* interrupt fires (button press) and resumes from here.
|
||||
*/
|
||||
void power_sleep_until_button(void);
|
||||
|
||||
@@ -1,7 +1,30 @@
|
||||
/**
|
||||
* @file radio.h
|
||||
* @brief RADIO peripheral driver -- NRF_1Mbit proprietary mode.
|
||||
*/
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
|
||||
/** @brief Configure the RADIO peripheral (mode, packet format, address, CRC, power, channel). */
|
||||
void radio_init(void);
|
||||
void radio_set_channel(uint8_t ch); /* 0-39, maps to 2402-2480 MHz */
|
||||
|
||||
/**
|
||||
* @brief Set the RF channel.
|
||||
* @param ch Channel index 0-39, maps to 2400+ch MHz (MAP=0).
|
||||
*/
|
||||
void radio_set_channel(uint8_t ch);
|
||||
|
||||
/**
|
||||
* @brief Transmit one packet synchronously.
|
||||
*
|
||||
* Loads @p data into the internal packet buffer, asserts TASKS_TXEN, and
|
||||
* returns after EVENTS_END fires. The RADIO is DISABLED automatically via
|
||||
* the END_DISABLE shortcut before the function returns.
|
||||
*
|
||||
* @param data Payload bytes.
|
||||
* @param len Payload length (0-255 bytes).
|
||||
*/
|
||||
void radio_tx(const uint8_t *data, uint8_t len);
|
||||
void radio_tx_burst(void); /* TX with FHSS hopping */
|
||||
|
||||
/** @brief Transmit a burst with FHSS hopping (not yet implemented). */
|
||||
void radio_tx_burst(void);
|
||||
|
||||
@@ -1,15 +1,16 @@
|
||||
/**
|
||||
* @file regs.h
|
||||
* @brief Hardware register bitfield unions for nRF52840 peripherals.
|
||||
*
|
||||
* Layout is guaranteed correct only with arm-none-eabi-gcc (LSB-first
|
||||
* bitfields). Bit ranges match nRF52840 Product Specification v1.7.
|
||||
*/
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
|
||||
/*
|
||||
* Hardware register bitfield unions for nRF52840 peripherals.
|
||||
* Layout is guaranteed correct only with arm-none-eabi-gcc (LSB-first bitfields).
|
||||
* Bit ranges match nRF52840 Product Specification v1.7.
|
||||
*/
|
||||
|
||||
/* GPIOTE */
|
||||
|
||||
/* CONFIG[n]: channel configuration */
|
||||
/** @brief GPIOTE CONFIG[n]: channel configuration register. */
|
||||
typedef union {
|
||||
struct {
|
||||
uint32_t MODE : 2; /* [1:0] 0=Disabled 1=Event 3=Task */
|
||||
@@ -33,7 +34,7 @@ typedef union {
|
||||
#define GPIOTE_POL_HITOLO 2u
|
||||
#define GPIOTE_POL_TOGGLE 3u
|
||||
|
||||
/* INTENSET / INTENCLR: interrupt enable */
|
||||
/** @brief GPIOTE INTENSET / INTENCLR: interrupt enable register. */
|
||||
typedef union {
|
||||
struct {
|
||||
uint32_t IN0 : 1; /* [0] channel 0 input event */
|
||||
@@ -52,7 +53,7 @@ typedef union {
|
||||
|
||||
/* RADIO */
|
||||
|
||||
/* FREQUENCY: radio channel */
|
||||
/** @brief RADIO FREQUENCY: RF channel selection register. */
|
||||
typedef union {
|
||||
struct {
|
||||
uint32_t FREQUENCY : 7; /* [6:0] offset from base frequency in MHz */
|
||||
@@ -66,7 +67,7 @@ typedef union {
|
||||
#define RADIO_MAP_DEFAULT 0u /* channel n -> 2400+n MHz */
|
||||
#define RADIO_MAP_BLE 1u /* channel n -> 2360+n MHz */
|
||||
|
||||
/* TXPOWER: transmit power */
|
||||
/** @brief RADIO TXPOWER: transmit power register. */
|
||||
typedef union {
|
||||
struct {
|
||||
int32_t TXPOWER : 8; /* [7:0] signed dBm: +8, +7, +6, +5, +4, +3, +2,
|
||||
@@ -76,7 +77,7 @@ typedef union {
|
||||
uint32_t reg;
|
||||
} radio_txpower_t;
|
||||
|
||||
/* MODE: radio data rate and modulation */
|
||||
/** @brief RADIO MODE: data rate and modulation register. */
|
||||
typedef union {
|
||||
struct {
|
||||
uint32_t MODE : 4; /* [3:0] 0=NRF_1Mbit 1=NRF_2Mbit 4=BLE_1Mbit ... */
|
||||
@@ -89,7 +90,7 @@ typedef union {
|
||||
#define RADIO_MODE_NRF_2MBIT 1u
|
||||
#define RADIO_MODE_BLE_1MBIT 4u
|
||||
|
||||
/* PCNF0: packet configuration register 0 */
|
||||
/** @brief RADIO PCNF0: packet configuration register 0 (header fields). */
|
||||
typedef union {
|
||||
struct {
|
||||
uint32_t LFLEN : 4; /* [3:0] length of LENGTH field in bits */
|
||||
@@ -106,7 +107,7 @@ typedef union {
|
||||
uint32_t reg;
|
||||
} radio_pcnf0_t;
|
||||
|
||||
/* PCNF1: packet configuration register 1 */
|
||||
/** @brief RADIO PCNF1: packet configuration register 1 (payload and address). */
|
||||
typedef union {
|
||||
struct {
|
||||
uint32_t MAXLEN : 8; /* [7:0] maximum payload length in bytes */
|
||||
@@ -120,7 +121,7 @@ typedef union {
|
||||
uint32_t reg;
|
||||
} radio_pcnf1_t;
|
||||
|
||||
/* CRCCNF: CRC configuration */
|
||||
/** @brief RADIO CRCCNF: CRC configuration register. */
|
||||
typedef union {
|
||||
struct {
|
||||
uint32_t LEN : 2; /* [1:0] 0=disabled 1=1 byte 2=2 bytes 3=3 bytes */
|
||||
@@ -136,7 +137,7 @@ typedef union {
|
||||
#define RADIO_CRCCNF_LEN_TWO 2u
|
||||
#define RADIO_CRCCNF_LEN_THREE 3u
|
||||
|
||||
/* SHORTS: shortcut register */
|
||||
/** @brief RADIO SHORTS: hardware shortcut register. */
|
||||
typedef union {
|
||||
struct {
|
||||
uint32_t READY_START : 1; /* [0] READY -> TASKS_START */
|
||||
|
||||
46
justfile
46
justfile
@@ -12,6 +12,8 @@ user_ns := `command -v podman >/dev/null 2>&1 \
|
||||
&& echo "--userns=keep-id" \
|
||||
|| echo "--user $(id -u):$(id -g)"`
|
||||
|
||||
src_files := "find /src/src /src/include -name '*.c' -o -name '*.h'"
|
||||
|
||||
# recipes
|
||||
# build container image (only rebuilt when Dockerfile changes)
|
||||
image-build:
|
||||
@@ -27,6 +29,44 @@ build: image-build
|
||||
-DCMAKE_BUILD_TYPE=MinSizeRel /src \
|
||||
&& ninja -C /src/{{build_dir}}"
|
||||
|
||||
# reformat all source files in-place with clang-format
|
||||
format: image-build
|
||||
{{engine}} run --rm \
|
||||
{{user_ns}} \
|
||||
-v "{{justfile_directory()}}:/src:z" \
|
||||
{{image}} \
|
||||
sh -c "{{src_files}} | xargs clang-format -i --style=file:/src/.clang-format"
|
||||
|
||||
# check formatting without modifying files (used in CI)
|
||||
format-check: image-build
|
||||
{{engine}} run --rm \
|
||||
{{user_ns}} \
|
||||
-v "{{justfile_directory()}}:/src:z" \
|
||||
{{image}} \
|
||||
sh -c "{{src_files}} | xargs clang-format --dry-run --Werror --style=file:/src/.clang-format"
|
||||
|
||||
# static analysis with cppcheck
|
||||
lint: image-build
|
||||
{{engine}} run --rm \
|
||||
{{user_ns}} \
|
||||
-v "{{justfile_directory()}}:/src:z" \
|
||||
{{image}} \
|
||||
sh -c "cppcheck --error-exitcode=1 \
|
||||
--enable=warning,style,performance,portability \
|
||||
--suppress=missingInclude \
|
||||
--inline-suppr \
|
||||
--std=c11 \
|
||||
-I /src/include \
|
||||
/src/src/"
|
||||
|
||||
# generate HTML documentation with Doxygen
|
||||
docs: image-build
|
||||
{{engine}} run --rm \
|
||||
{{user_ns}} \
|
||||
-v "{{justfile_directory()}}:/src:z" \
|
||||
{{image}} \
|
||||
sh -c "cd /src && doxygen Doxyfile"
|
||||
|
||||
# flash firmware via pyocd on the host (requires USB / DAPLink)
|
||||
flash: build
|
||||
pyocd flash --target nrf52840 {{build_dir}}/firmware.hex
|
||||
@@ -35,10 +75,10 @@ flash: build
|
||||
gdbserver:
|
||||
pyocd gdbserver --target nrf52840 --port 3333
|
||||
|
||||
# remove build artifacts
|
||||
# remove build artifacts and generated docs
|
||||
clean:
|
||||
rm -rf {{build_dir}}
|
||||
rm -rf {{build_dir}} docs
|
||||
|
||||
# remove build artifacts AND the container image
|
||||
# remove build artifacts, docs AND the container image
|
||||
clean-all: clean
|
||||
{{engine}} rmi {{image}} 2>/dev/null || true
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
/** @file fhss.c
|
||||
* @brief FHSS channel sequencer implementation.
|
||||
*/
|
||||
#include "fhss.h"
|
||||
#include <aes.h>
|
||||
|
||||
@@ -6,8 +9,7 @@
|
||||
|
||||
/* TODO: replace with a real shared secret before deployment */
|
||||
static const uint8_t shared_key[16] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
};
|
||||
|
||||
static uint32_t slot;
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
/** @file main.c
|
||||
* @brief Entry point: initialise peripherals and run the PTT event loop.
|
||||
*/
|
||||
#include "radio.h"
|
||||
#include "power.h"
|
||||
#include <stdint.h>
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
/** @file power.c
|
||||
* @brief Power management implementation.
|
||||
*/
|
||||
#include "power.h"
|
||||
#include "regs.h"
|
||||
#include <nrf52840.h>
|
||||
@@ -17,8 +20,7 @@ void power_init(void)
|
||||
.PSEL = BUTTON_PIN,
|
||||
.PORT = 0u,
|
||||
.POLARITY = GPIOTE_POL_LOTOHI,
|
||||
}
|
||||
}.reg;
|
||||
}}.reg;
|
||||
|
||||
NRF_GPIOTE->INTENSET = (gpiote_inten_t){.bit.IN0 = 1u}.reg;
|
||||
|
||||
|
||||
44
src/radio.c
44
src/radio.c
@@ -1,3 +1,6 @@
|
||||
/** @file radio.c
|
||||
* @brief RADIO peripheral driver implementation.
|
||||
*/
|
||||
#include "radio.h"
|
||||
#include "regs.h"
|
||||
#include <nrf52840.h>
|
||||
@@ -27,20 +30,17 @@ static uint8_t pkt_buf[BUF_SIZE];
|
||||
|
||||
void radio_init(void)
|
||||
{
|
||||
NRF_RADIO->MODE = (radio_mode_t){
|
||||
.bit = { .MODE = RADIO_MODE_NRF_1MBIT }
|
||||
}.reg;
|
||||
NRF_RADIO->MODE = (radio_mode_t){.bit = {.MODE = RADIO_MODE_NRF_1MBIT}}.reg;
|
||||
|
||||
/* 8-bit LENGTH field, no S0/S1, 8-bit preamble, CRC not part of LENGTH */
|
||||
NRF_RADIO->PCNF0 = (radio_pcnf0_t){
|
||||
.bit = { .LFLEN = 8, .S0LEN = 0, .S1LEN = 0, .PLEN = 0, .CRCINC = 0 }
|
||||
}.reg;
|
||||
NRF_RADIO->PCNF0 =
|
||||
(radio_pcnf0_t){.bit = {.LFLEN = 8, .S0LEN = 0, .S1LEN = 0, .PLEN = 0, .CRCINC = 0}}.reg;
|
||||
|
||||
/* max 255-byte payload, 3-byte base address, little-endian, no whitening */
|
||||
NRF_RADIO->PCNF1 = (radio_pcnf1_t){
|
||||
.bit = { .MAXLEN = MAX_PAYLOAD, .STATLEN = 0, .BALEN = 3,
|
||||
.ENDIAN = 0, .WHITEEN = 0 }
|
||||
}.reg;
|
||||
NRF_RADIO->PCNF1 =
|
||||
(radio_pcnf1_t){
|
||||
.bit = {.MAXLEN = MAX_PAYLOAD, .STATLEN = 0, .BALEN = 3, .ENDIAN = 0, .WHITEEN = 0}}
|
||||
.reg;
|
||||
|
||||
NRF_RADIO->BASE0 = RADIO_BASE0;
|
||||
NRF_RADIO->PREFIX0 = RADIO_PREFIX0;
|
||||
@@ -48,33 +48,29 @@ void radio_init(void)
|
||||
NRF_RADIO->RXADDRESSES = 1; /* receive on logical address 0 */
|
||||
|
||||
/* 2-byte CRC, skip address field */
|
||||
NRF_RADIO->CRCCNF = (radio_crccnf_t){
|
||||
.bit = { .LEN = RADIO_CRCCNF_LEN_TWO, .SKIPADDR = 1 }
|
||||
}.reg;
|
||||
NRF_RADIO->CRCCNF = (radio_crccnf_t){.bit = {.LEN = RADIO_CRCCNF_LEN_TWO, .SKIPADDR = 1}}.reg;
|
||||
NRF_RADIO->CRCPOLY = 0x11021u; /* CRC-16/CCITT */
|
||||
NRF_RADIO->CRCINIT = 0xFFFFu;
|
||||
|
||||
NRF_RADIO->TXPOWER = (radio_txpower_t){
|
||||
NRF_RADIO->TXPOWER =
|
||||
(radio_txpower_t){
|
||||
.bit = {.TXPOWER = 0} /* 0 dBm */
|
||||
}.reg;
|
||||
}
|
||||
.reg;
|
||||
|
||||
NRF_RADIO->FREQUENCY = (radio_frequency_t){
|
||||
.bit = { .FREQUENCY = DEFAULT_CHANNEL, .MAP = RADIO_MAP_DEFAULT }
|
||||
}.reg;
|
||||
NRF_RADIO->FREQUENCY =
|
||||
(radio_frequency_t){.bit = {.FREQUENCY = DEFAULT_CHANNEL, .MAP = RADIO_MAP_DEFAULT}}.reg;
|
||||
|
||||
/* READY -> START and END -> DISABLE shortcuts so CPU only triggers TXEN */
|
||||
NRF_RADIO->SHORTS = (radio_shorts_t){
|
||||
.bit = { .READY_START = 1, .END_DISABLE = 1 }
|
||||
}.reg;
|
||||
NRF_RADIO->SHORTS = (radio_shorts_t){.bit = {.READY_START = 1, .END_DISABLE = 1}}.reg;
|
||||
|
||||
NRF_RADIO->PACKETPTR = (uint32_t)pkt_buf;
|
||||
}
|
||||
|
||||
void radio_set_channel(uint8_t ch)
|
||||
{
|
||||
NRF_RADIO->FREQUENCY = (radio_frequency_t){
|
||||
.bit = { .FREQUENCY = ch, .MAP = RADIO_MAP_DEFAULT }
|
||||
}.reg;
|
||||
NRF_RADIO->FREQUENCY =
|
||||
(radio_frequency_t){.bit = {.FREQUENCY = ch, .MAP = RADIO_MAP_DEFAULT}}.reg;
|
||||
}
|
||||
|
||||
void radio_tx(const uint8_t *data, uint8_t len)
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
/** @file startup.c
|
||||
* @brief Vector table and Reset_Handler for nRF52840 (no SoftDevice).
|
||||
*/
|
||||
#include <stdint.h>
|
||||
|
||||
/* linker script symbols */
|
||||
@@ -14,7 +17,8 @@ void Reset_Handler(void);
|
||||
|
||||
static void __attribute__((used)) Default_Handler(void)
|
||||
{
|
||||
while (1);
|
||||
while (1)
|
||||
;
|
||||
}
|
||||
|
||||
/* ARM Cortex-M4 core exceptions */
|
||||
@@ -32,8 +36,10 @@ void SysTick_Handler(void) __attribute__((weak, alias("Default_Handler")));
|
||||
void POWER_CLOCK_IRQHandler(void) __attribute__((weak, alias("Default_Handler")));
|
||||
void RADIO_IRQHandler(void) __attribute__((weak, alias("Default_Handler")));
|
||||
void UARTE0_UART0_IRQHandler(void) __attribute__((weak, alias("Default_Handler")));
|
||||
void SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQHandler(void) __attribute__((weak, alias("Default_Handler")));
|
||||
void SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1_IRQHandler(void) __attribute__((weak, alias("Default_Handler")));
|
||||
void SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQHandler(void)
|
||||
__attribute__((weak, alias("Default_Handler")));
|
||||
void SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1_IRQHandler(void)
|
||||
__attribute__((weak, alias("Default_Handler")));
|
||||
void NFCT_IRQHandler(void) __attribute__((weak, alias("Default_Handler")));
|
||||
void GPIOTE_IRQHandler(void) __attribute__((weak, alias("Default_Handler")));
|
||||
void SAADC_IRQHandler(void) __attribute__((weak, alias("Default_Handler")));
|
||||
@@ -77,8 +83,7 @@ void SPIM3_IRQHandler(void) __attribute__((weak, al
|
||||
|
||||
typedef void (*vector_fn)(void);
|
||||
|
||||
__attribute__((section(".isr_vector"), used))
|
||||
const vector_fn vectors[64] = {
|
||||
__attribute__((section(".isr_vector"), used)) const vector_fn vectors[64] = {
|
||||
/* 0 */ (vector_fn)&_estack,
|
||||
/* 1 */ Reset_Handler,
|
||||
/* 2 */ NMI_Handler,
|
||||
@@ -153,16 +158,19 @@ void Reset_Handler(void)
|
||||
/* copy .data initializers from Flash to RAM */
|
||||
uint32_t *src = &_sidata;
|
||||
uint32_t *dst = &_sdata;
|
||||
// cppcheck-suppress comparePointers
|
||||
while (dst < &_edata) {
|
||||
*dst++ = *src++;
|
||||
}
|
||||
|
||||
/* zero .bss */
|
||||
dst = &_sbss;
|
||||
// cppcheck-suppress comparePointers
|
||||
while (dst < &_ebss) {
|
||||
*dst++ = 0u;
|
||||
}
|
||||
|
||||
main();
|
||||
while (1);
|
||||
while (1)
|
||||
;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user