- Fully open toolchain: arm-none-eabi-gcc inside Podman/Docker container - Platform-agnostic build via justfile (auto-detects podman vs docker) - CMake + Ninja build system with arm-none-eabi toolchain file - nRF52840 linker script and startup with full 64-entry vector table - Register access via typed bitfield unions (include/regs.h) - FHSS channel sequencer: AES-128-ECB PRNG over 40 channels (2402-2480 MHz) - Low-power sleep via SYSTEM_ON WFI + GPIOTE wakeup on button press - Vendor deps as shallow git submodules: nrfx, CMSIS_5, tiny-AES-c
169 lines
8.5 KiB
C
169 lines
8.5 KiB
C
#include <stdint.h>
|
||
|
||
/* linker script symbols */
|
||
extern uint32_t _sidata; /* load address of .data in Flash */
|
||
extern uint32_t _sdata; /* start of .data in RAM */
|
||
extern uint32_t _edata; /* end of .data in RAM */
|
||
extern uint32_t _sbss;
|
||
extern uint32_t _ebss;
|
||
extern uint32_t _estack; /* address equals initial SP value */
|
||
|
||
extern int main(void);
|
||
|
||
void Reset_Handler(void);
|
||
|
||
static void __attribute__((used)) Default_Handler(void)
|
||
{
|
||
while (1);
|
||
}
|
||
|
||
/* ARM Cortex-M4 core exceptions */
|
||
void NMI_Handler(void) __attribute__((weak, alias("Default_Handler")));
|
||
void HardFault_Handler(void) __attribute__((weak, alias("Default_Handler")));
|
||
void MemManage_Handler(void) __attribute__((weak, alias("Default_Handler")));
|
||
void BusFault_Handler(void) __attribute__((weak, alias("Default_Handler")));
|
||
void UsageFault_Handler(void) __attribute__((weak, alias("Default_Handler")));
|
||
void SVC_Handler(void) __attribute__((weak, alias("Default_Handler")));
|
||
void DebugMon_Handler(void) __attribute__((weak, alias("Default_Handler")));
|
||
void PendSV_Handler(void) __attribute__((weak, alias("Default_Handler")));
|
||
void SysTick_Handler(void) __attribute__((weak, alias("Default_Handler")));
|
||
|
||
/* nRF52840 peripheral IRQs (IRQ0–IRQ47) */
|
||
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 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")));
|
||
void TIMER0_IRQHandler(void) __attribute__((weak, alias("Default_Handler")));
|
||
void TIMER1_IRQHandler(void) __attribute__((weak, alias("Default_Handler")));
|
||
void TIMER2_IRQHandler(void) __attribute__((weak, alias("Default_Handler")));
|
||
void RTC0_IRQHandler(void) __attribute__((weak, alias("Default_Handler")));
|
||
void TEMP_IRQHandler(void) __attribute__((weak, alias("Default_Handler")));
|
||
void RNG_IRQHandler(void) __attribute__((weak, alias("Default_Handler")));
|
||
void ECB_IRQHandler(void) __attribute__((weak, alias("Default_Handler")));
|
||
void CCM_AAR_IRQHandler(void) __attribute__((weak, alias("Default_Handler")));
|
||
void WDT_IRQHandler(void) __attribute__((weak, alias("Default_Handler")));
|
||
void RTC1_IRQHandler(void) __attribute__((weak, alias("Default_Handler")));
|
||
void QDEC_IRQHandler(void) __attribute__((weak, alias("Default_Handler")));
|
||
void COMP_LPCOMP_IRQHandler(void) __attribute__((weak, alias("Default_Handler")));
|
||
void SWI0_EGU0_IRQHandler(void) __attribute__((weak, alias("Default_Handler")));
|
||
void SWI1_EGU1_IRQHandler(void) __attribute__((weak, alias("Default_Handler")));
|
||
void SWI2_EGU2_IRQHandler(void) __attribute__((weak, alias("Default_Handler")));
|
||
void SWI3_EGU3_IRQHandler(void) __attribute__((weak, alias("Default_Handler")));
|
||
void SWI4_EGU4_IRQHandler(void) __attribute__((weak, alias("Default_Handler")));
|
||
void SWI5_EGU5_IRQHandler(void) __attribute__((weak, alias("Default_Handler")));
|
||
void TIMER3_IRQHandler(void) __attribute__((weak, alias("Default_Handler")));
|
||
void TIMER4_IRQHandler(void) __attribute__((weak, alias("Default_Handler")));
|
||
void PWM0_IRQHandler(void) __attribute__((weak, alias("Default_Handler")));
|
||
void PDM_IRQHandler(void) __attribute__((weak, alias("Default_Handler")));
|
||
void MWU_IRQHandler(void) __attribute__((weak, alias("Default_Handler")));
|
||
void PWM1_IRQHandler(void) __attribute__((weak, alias("Default_Handler")));
|
||
void PWM2_IRQHandler(void) __attribute__((weak, alias("Default_Handler")));
|
||
void SPIM2_SPIS2_SPI2_IRQHandler(void) __attribute__((weak, alias("Default_Handler")));
|
||
void RTC2_IRQHandler(void) __attribute__((weak, alias("Default_Handler")));
|
||
void I2S_IRQHandler(void) __attribute__((weak, alias("Default_Handler")));
|
||
void FPU_IRQHandler(void) __attribute__((weak, alias("Default_Handler")));
|
||
void USBD_IRQHandler(void) __attribute__((weak, alias("Default_Handler")));
|
||
void UARTE1_IRQHandler(void) __attribute__((weak, alias("Default_Handler")));
|
||
void QSPI_IRQHandler(void) __attribute__((weak, alias("Default_Handler")));
|
||
void CRYPTOCELL_IRQHandler(void) __attribute__((weak, alias("Default_Handler")));
|
||
void PWM3_IRQHandler(void) __attribute__((weak, alias("Default_Handler")));
|
||
void SPIM3_IRQHandler(void) __attribute__((weak, alias("Default_Handler")));
|
||
|
||
/* ── vector table: 64 entries (16 core + 48 IRQs) ───────────────────────── */
|
||
|
||
typedef void (*vector_fn)(void);
|
||
|
||
__attribute__((section(".isr_vector"), used))
|
||
const vector_fn vectors[64] = {
|
||
/* 0 */ (vector_fn)&_estack,
|
||
/* 1 */ Reset_Handler,
|
||
/* 2 */ NMI_Handler,
|
||
/* 3 */ HardFault_Handler,
|
||
/* 4 */ MemManage_Handler,
|
||
/* 5 */ BusFault_Handler,
|
||
/* 6 */ UsageFault_Handler,
|
||
/* 7 */ 0,
|
||
/* 8 */ 0,
|
||
/* 9 */ 0,
|
||
/* 10 */ 0,
|
||
/* 11 */ SVC_Handler,
|
||
/* 12 */ DebugMon_Handler,
|
||
/* 13 */ 0,
|
||
/* 14 */ PendSV_Handler,
|
||
/* 15 */ SysTick_Handler,
|
||
|
||
/* IRQ0 */ POWER_CLOCK_IRQHandler,
|
||
/* IRQ1 */ RADIO_IRQHandler,
|
||
/* IRQ2 */ UARTE0_UART0_IRQHandler,
|
||
/* IRQ3 */ SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQHandler,
|
||
/* IRQ4 */ SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1_IRQHandler,
|
||
/* IRQ5 */ NFCT_IRQHandler,
|
||
/* IRQ6 */ GPIOTE_IRQHandler,
|
||
/* IRQ7 */ SAADC_IRQHandler,
|
||
/* IRQ8 */ TIMER0_IRQHandler,
|
||
/* IRQ9 */ TIMER1_IRQHandler,
|
||
/* IRQ10 */ TIMER2_IRQHandler,
|
||
/* IRQ11 */ RTC0_IRQHandler,
|
||
/* IRQ12 */ TEMP_IRQHandler,
|
||
/* IRQ13 */ RNG_IRQHandler,
|
||
/* IRQ14 */ ECB_IRQHandler,
|
||
/* IRQ15 */ CCM_AAR_IRQHandler,
|
||
/* IRQ16 */ WDT_IRQHandler,
|
||
/* IRQ17 */ RTC1_IRQHandler,
|
||
/* IRQ18 */ QDEC_IRQHandler,
|
||
/* IRQ19 */ COMP_LPCOMP_IRQHandler,
|
||
/* IRQ20 */ SWI0_EGU0_IRQHandler,
|
||
/* IRQ21 */ SWI1_EGU1_IRQHandler,
|
||
/* IRQ22 */ SWI2_EGU2_IRQHandler,
|
||
/* IRQ23 */ SWI3_EGU3_IRQHandler,
|
||
/* IRQ24 */ SWI4_EGU4_IRQHandler,
|
||
/* IRQ25 */ SWI5_EGU5_IRQHandler,
|
||
/* IRQ26 */ TIMER3_IRQHandler,
|
||
/* IRQ27 */ TIMER4_IRQHandler,
|
||
/* IRQ28 */ PWM0_IRQHandler,
|
||
/* IRQ29 */ PDM_IRQHandler,
|
||
/* IRQ30 */ 0, /* reserved */
|
||
/* IRQ31 */ 0, /* reserved */
|
||
/* IRQ32 */ MWU_IRQHandler,
|
||
/* IRQ33 */ PWM1_IRQHandler,
|
||
/* IRQ34 */ PWM2_IRQHandler,
|
||
/* IRQ35 */ SPIM2_SPIS2_SPI2_IRQHandler,
|
||
/* IRQ36 */ RTC2_IRQHandler,
|
||
/* IRQ37 */ I2S_IRQHandler,
|
||
/* IRQ38 */ FPU_IRQHandler,
|
||
/* IRQ39 */ USBD_IRQHandler,
|
||
/* IRQ40 */ UARTE1_IRQHandler,
|
||
/* IRQ41 */ QSPI_IRQHandler,
|
||
/* IRQ42 */ CRYPTOCELL_IRQHandler,
|
||
/* IRQ43 */ 0, /* reserved */
|
||
/* IRQ44 */ 0, /* reserved */
|
||
/* IRQ45 */ PWM3_IRQHandler,
|
||
/* IRQ46 */ 0, /* reserved */
|
||
/* IRQ47 */ SPIM3_IRQHandler,
|
||
};
|
||
|
||
/* ── Reset_Handler ───────────────────────────────────────────────────────── */
|
||
|
||
void Reset_Handler(void)
|
||
{
|
||
/* copy .data initializers from Flash to RAM */
|
||
uint32_t *src = &_sidata;
|
||
uint32_t *dst = &_sdata;
|
||
while (dst < &_edata) {
|
||
*dst++ = *src++;
|
||
}
|
||
|
||
/* zero .bss */
|
||
dst = &_sbss;
|
||
while (dst < &_ebss) {
|
||
*dst++ = 0u;
|
||
}
|
||
|
||
main();
|
||
while (1);
|
||
}
|